이번에 회사에서 작업을 하는데

이런 뷰를 만들어야 할 일이 생겼다.

이전에는 \n과 스페이스(또는 공백문자)로 맞추려고했으나, 안드로이드는 워낙 지원하는 단말기가 많아 각 단말기별/폰트별로 결과물에 차이가 발생하였다.

 

검색해보니 LeadingMarginSpan이라는 게 있었는데 적용해보니 이런 식으로 되는 것을 확인함.

\n으로 인한 줄바꿈은 무조건 새로운 줄이라고 인식해서 그런 것 같았다.

 

public abstract class LeadingSubTextSpan implements LeadingMarginSpan {
    int leading=10;   //얼마만큼 들여쓰기 할 건지

    private int margin=0;

    public LeadingSubTextSpan(int leading) {
        this.leading = leading;
    }

    public abstract boolean isSubText(String text);    //여백 줘야 하는 줄인지 체크하는 메소드

    @Override
    public int getLeadingMargin(boolean b) {
        return margin;
    }

    @Override
    public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean isFirst, Layout layout) {
        int m = 0;
        if(start > 0){
            String t = text.toString().substring(start-1);
            if(t.startsWith("\n") && isSubText(t)) {
                m = leading;
            }
        }
        margin = m;
    }
}

abstract 클래스이고, isSubText()라는 메소드를 통해 줄바꿈을 할 것인지 판단하도록 하였다. 인자로 넘기는 text는 각 줄의 텍스트..

사용할 때는 아래와 같이 사용한다.

SpannableStringBuilder b = new SpannableStringBuilder(stringBuilder);
int leading = 100;
b.setSpan(new LeadingSubTextSpan(leading) {
    @Override
    public boolean isSubText(String text) {
        return !text.startsWith("\n*");
    }
}, 0, b.length(), 0);
textView.setText(b);

leading 부분에 숫자를 넣어도 되지만

textView.getPaint().measureText("가나다");

이런 식으로 하면 해당 textView에서 '가나다'라는 String이 표시될 때의 너비를 가져올 수 있으니

활용해서 사용하는 게 편할 것 같다.

 

음.. 이런 기능을 지원하지 않았다는 게 좀 신기할 따름인데

알고보니 원래 있었던 기능인데 내가 몰랐을 수도 있겠다는 생각이 드네 ㅜㅜ ..

기존에 API로 제공한다면 알려주시길 바람!

spinner에 배경으로 쓰려고 xml shape를 만드는 중인데 자꾸 오류가 났다.

xml에서 미리보기 할 때는 

이렇게 잘 나오는데..

 

실행을 하면

이렇게 나오는 것이다.

 

 

▼문제가 된 코드

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        ...
    </item>
    <item android:gravity="center_vertical|right">
        <bitmap
            android:src="@drawable/arrow" />
    </item>
</layer-list>

 

▼ 옳게 수정한 코드

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        ...
    </item>
    <item >
        <bitmap
            android:gravity="center_vertical|right"
            android:src="@drawable/arrow" />
    </item>
</layer-list>

 

화살표 <item> 에 android:gravity를 지정하는 게 아니라

화살표 <item> 내부의 <bitmap>에 지정해줘야 했음.

 

 

 

검색하기 애매해서 혼났다.

 


[참고링크] stackoverflow.com/questions/37411637/change-spinner-dropdown-icon/37461505

 

유튜브의 '센치한개발자' 채널의 코틀린 강의를 들으면서 하는 벼락치기 공부입니다!

기본적인 부분은 유튜브 강의로 보고 나서 3년 전에 산 책 한 번 더 읽어야겠다..

 

 

 

1. 배열(listOf) + 반복문(for)

fun main() {
    var arr = listOf("가", "나")	//변경 불가능한 배열
    
    //기본 반복문
    for(item in arr) {
        println(item);
    }
}
<코드 실행 결과>
가
나

listOf로 생성한 배열은 구조를 변경할 수 없다.

즉 JAVA의 Array와 비슷하다고 볼 수 있겠다.

 

반복문의 경우 for을 사용했는데, 

자바의 foreach문(향상된 반복문)과 비슷한 모양새를 하고 있다.

 

2. 배열(mutableListOf()) + 반복문 (for ... withIndex())

fun main() {
    var arr2 = mutableListOf("A", "B")	//변경 가능한 배열

    //index 값 가져오는 배열문
    for((index, item) in arr2.withIndex()) {
        println("$index / $item");
    }
}
<코드 실행 결과>
0 / A
1 / B

mutableListOf() 로 생성한 배열은 구조를 변경할 수 있다. (add(), remove())

즉 JAVA의 LIST와 비슷하다고 볼 수 있다.

 

이 코드에서 쓰인 for문은 첫번째 것과 모양이 비슷하면서 다른데

첫 번째 반복문은 단순히 안에 들어있는 값만 가져오면 될 때 쓴다면

이건 현재 몇 번째 실행중인지에 대한 index값을 가져오려 할 때 사용할 수 있다.

 

 

 

 


이전부터 생각했지만 코틀린이라는 녀석.. 굉장히 대충대충(?)인 느낌인 게..

String이든 Int든 일단 val아니면 var로 때웠는데

이번에 배열 선언할 때도 기대를 저버리지 않고(?) var 또는 val를 이용하여 선언할 수 있다는 걸 볼 수 있다.

게으른 개발자를 위해서인걸까...?

'개발 > Kotlin' 카테고리의 다른 글

코틀린 공부 - 함수(1)  (0) 2021.08.02
코틀린 기초 5 - object  (0) 2020.06.25
코틀린 기초 - 4(고차함수, 람다)  (0) 2020.06.24
코틀린 기초 - 3 (if~else, when)  (0) 2020.06.23
코틀린 기초 - 1  (0) 2020.06.16

코틀린이 나오고 안드로이드의 공식 언어로 채택된 지도 꽤 시간이 흘렀으나 이제야 공부하게 된 나 자신을 반성 또 반성.. 늦게나마 공부를 시작하게 되었다.

일단 올해 내로 공공 API를 사용하는 앱을 만들어 서비스하는 것을 목표로 열심히 해 보기로..

------------

이번 시간에는 기본 변수형의 차이에 대한 차이를 학습하였다.

 

1. val 변수 (value)

fun main() {
    val first = "Hello"	//변경 불가능한 변수
    
    println(first)
	//first = "Hello2"	//변경 불가(에러)

}
<코드 실행 결과>
Hello

val 은 Java의 fianl 변수와 대응하며, 값이 한 번 할당되면 이를 변경할 수 없다.

위의 코드에서 fist = "hello2" 부분을 주석해제하면 에러가 발생하게 된다.

 

2. var 변수 (variable)

fun main() {
    var second:String = "TEST";
    var third:String? = null
    
    println(second)
    second = "WORLD"
    println(second)

    println(third)
}
<코드 실행 결과>
TEST
WORLD
null

var 은 일반적인 변수로, 값을 여러 번 할당할 수 있다.

자료형 뒤에 ? 가 붙으면 해당 변수에 null을 할당할 수 있다는 것을 의미한다.

 

사실 꼭 초기값을 할당해주지 않고 var {변수명}:{자료형} 으로 쓸 수 있다.

var number:Int

 

3. 함수(function)

fun main() {
    var third:String? = null
    
    println(third)
    third = getString()
    println(third)
    third = getSum(2, 5)
    println(third)

    end()
}

fun getString() : String {
    return "GET STRING FROM METHOD";
}

fun getSum(i : Int, i2 : Int) : String {
    return "get Sum (" + i + " + " + i2 + " = " + (i+i2) + ")"
}

fun end() {
    println("end of line")
}
<코드 실행 결과>
null
GET STRING FROM METHOD
get Sum (2 + 5 = 7)
end of line

함수 선언 시 fun 이라는 키워드를 사용한다.

반환값이 있는 경우 (getString(), getSum()) 변수 선언 시와 마찬가지로 함수명 뒤에 자료형을 적어주고, 반환값이 없는 경우에는 이를 생략할 수 있다. 

JAVA와의 차이라면 자료형이 앞에 위치하냐 뒤에 위치하냐의 차이가 아닌가 싶다.

'개발 > Kotlin' 카테고리의 다른 글

코틀린 공부 - 함수(1)  (0) 2021.08.02
코틀린 기초 5 - object  (0) 2020.06.25
코틀린 기초 - 4(고차함수, 람다)  (0) 2020.06.24
코틀린 기초 - 3 (if~else, when)  (0) 2020.06.23
코틀린 기초 - 2 (배열, 반복문)  (0) 2020.06.16

1. 레이아웃 애니메이션 넣기

https://proandroiddev.com/enter-animation-using-recyclerview-and-layoutanimation-part-1-list-75a874a5d213


** <layoutAnimation> 요소에 duration 속성을 지정하지 않으면 애니메이션이 실행되지 않음.


2. 각 셀마다 애니메이션 나오게 하기

어댑터 안의 onBindHolder 내에 아래의 코드 삽입

(lastPosition은 어댑터 클래스의 전역 변수이며 초기값은 0 또는 -1)


if(position != lastPosition){

    Animation animation;

    if(position > lastPosition && position != 0) {

        animation = AnimationUtils.loadAnimation(holder.itemView.getContext(), R.anim.anim_slideup);    //아래로 스크롤 시 보여질 애니메이션

    }else{

        animation = AnimationUtils.loadAnimation(holder.itemView.getContext(), R.anim.anim_slidedown);    //위로 스크롤 시 보여질 애니메이션

    }

    holder.itemView.startAnimation(animation);

    lastPosition = position;

}


** 아이템을 추가 또는 삭제 할 때 lastPosition을 해당 아이템의 position으로 설정하면 추가/삭제 시 애니메이션 발생하지 않음.

ex )

private void add(int index, TextData data) {

    //데이터베이스에 데이터 넣기(단일)

    lastPosition = index;

    dataList.add(index, data);

    notifyItemInserted(index);

}


private void remove(TextData data) {

    //데이터베이스에서 데이터 지우기(단일)

    int removeIndex = dataList.indexOf(data);

    lastPosition = removeIndex;

    dataList.remove(removeIndex);

    notifyItemRemoved(removeIndex);

}


3. 기본 추가/삭제 애니메이션이 보여지길 원한다면.. 

notifyItemInserted, notifyItemRemoved를 적용(위의 코드의 파란색 형광펜 참조)

+ Recent posts