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

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

이전에는 \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

 

이 포스팅은 아래 포스팅을 기반으로 하여 쓰여졌습니다. 
> https://like-tomato.tistory.com/156 [토마토의 일상 얘기]

원본 포스팅 작성자 분께서는 부디 복 많이 받으시고 적게 일하시고 많이 버시길..


Notification을 클릭 시 앱이 실행되게 해 달라는 요청이 들어옴. 세부 조건은 아래와 같았음.

 

<조건>

- 앱이 실행 중일 때는 아무 반응 없게

- 홈 버튼 등을 눌러서 백그라운드에 위치했을 때는 앱을 포그라운드로 가져오고 가장 최근에 실행했던 액티비티 띄우기

- 앱이 완전히 종료되었을 때(엄밀히 말하자면 완전히 종료되었다는 건 애매한 표현이지만)는 앱이 다시 실행되게

 

구글링 하던 중 위 링크에 있는 코드를 기반으로 하여 구현하니 조건에 맞게 실행됨을 확인함.

Intent intent = new Intent(getBaseContext(), ActSplash.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pIntent = PendingIntent.getActivity(getBaseContext(), NotificationHelper.ID_FCM, intent, PendingIntent.FLAG_UPDATE_CURRENT);

PendingIntent.getActivity의 마지막 인자로 넘겨주는 Flag에 따라 차이가 있는지는 잘 모르겠다. 나중에 확인 해 봐야 할 듯.

 

왜 이렇게 되는지 자세한 내용은 이후 다시 보충하겠음!

Firestore를 사용하게 되어 메모 겸 요약본을 작성한다.

문서가 꽤 잘되있어 처음 시작은 어렵지 않을듯.


** firestore 지원 DataType

https://firebase.google.com/docs/firestore/manage-data/data-types?authuser=0



** firestore 데이터 가져오기

https://firebase.google.com/docs/firestore/query-data/get-data?authuser=0



** 시작하기 전에 권한이 없다고 나온다면..


권한에 들어가서 저 부분을 true로 바꾸면 된다. (저렇게 하면 읽기 쓰기 허용)








예를 들어 아래와 같은 데이터를 등록했다고 할 때..




database.document("notice/main").get().addOnCompleteListener(task -> {

    if(task.isSuccessful()){

        //성공

        DocumentSnapshot document = task.getResult();

        List list = (List) document.getData().get("list");

        for(int i=0;i<list.size();i++){

            Log.i("TEST", "data["+i+"] > " + list.get(i).toString());

            HashMap map = (HashMap) list.get(i);

            NoticeData data = new NoticeData();

            data.setTitle(map.get("title").toString());

            data.setContent(map.get("content").toString().replace("\\n", "\n"));

            data.setRegDate((Date) map.get("regdate"));

            Log.i("TEST", "["+i+"] > " + (list.get(i) instanceof HashMap) + " / " + (list.get(i).getClass().getName()) + " / " + list.get(i).toString());

        }

    }else{

         //실패

    }

};



한 줄씩 보자면..

** database.document("notice/main").get().addOnCompleteListener(task -> {

- Document를 가져올 것이라서 document(Colloction이름/Document이름).get()을 사용

- task 는 Task<DocumentSnapShot>이다.


** DocumentSnapshot document = task.getResult();

- 해당 문서 내부의 항목을 가져옴. (HashMap<String, Object> 형태


** List list = (List) document.getData().get("list");


- list라는 이름으로 등록된 필드를 가져옴



** HashMap map = (HashMap) list.get(i);


- Object 형식으로 저장한 데이터를 가져올 때는 Map을 사용함.


** data.setContent(map.get("content").toString().replace("\\n", "\n"));

- 개행문자가 그대로 입력되기 때문에 개행문자를 다시 한 번 변환해준다. (\\으로 입력해야 "\" 문자로 인식됨)


** data.setRegDate((Date) map.get("regdate"));

- 서버에 등록된 Timestamp를 바로 Date로 변환하기 위해서는 아래와 같은 코드를 사전에 입력해두어야 한다.

        database = FirebaseFirestore.getInstance();

        FirebaseFirestoreSettings.Builder settings = new FirebaseFirestoreSettings.Builder();

        settings.setTimestampsInSnapshotsEnabled(true);

        database.setFirestoreSettings(settings.build());

        database.document(....).get()....




** 

문서 내부에 list가 아니라 특정 오브젝트의 형태로 만들어져있다면 

toObject 메소드를 사용하여 손쉽게 Custom Object로 변환할 수 있다.


** 문제점

- 26버전 아래의 TextView에 app:autoSizeTextType 관련 속성이 동작 안 하는 오류 발생

- java 파일에서 TextViewCompat을 사용하는 방법으로도 적용되지 않았음.

- xml파일에서 prefix를 android로 하면 동작하나 app으로 하면 동작하지 않았음.



** 해결

- TextView의 height 값에 제한을 준다. (wrap_content는 쓰지 않는 게 좋음. 만약 wrap_content를 쓰는 경우에는 maxLine 등과 함께 사용)

- singleLine 속성 대신 maxLine 속성을 사용한다.

- TextView 대신 android.support.v7.widget.AppCompatTextView를 사용


** 참고

https://stackoverflow.com/questions/44118002/autosizing-of-textview-doesnt-work-android-o

+ Recent posts