상세 컨텐츠

본문 제목

안드로이드 채팅 ui 만들기 관련 리스트뷰(ListView)의 layout_weight 옵션을 이용한 채팅 GUI 구현, 카카오 채팅 말풍선

스마트기기개발관련/안드로이드 개발

by AlrepondTech 2020. 9. 21. 04:20

본문

반응형

 

 

 

 

=======================

=======================

=======================

 

 

 

 

 

 

 

출처: http://www.androidpub.com/2399994

 

문자나 카톡의 말풍선은 이미지인가요?

단다라단

Multi Line 이더라도 깨지지 않는걸 보니 이미지는 아닌 것 같은데..

 

ListView 인가요?

 

어떻게 말풍선 스타일을 입히는지 아시는 분..

 

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

 

isul

9 patch 이미지입니다.

2012.12.16 20:34:04

dingpong

위에 분이 말씀하신대로 나인패치 이미지로 적용하면 안깨집니다.

2012.12.16 22:35:20

아르샤빈

Textview에 백그라운드 이미지에 나인패치이미지넣고 wrap-content 적용하심 될듯

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: http://www.androidpub.com/2096

 

Android의 9 patch(나인패치) drawable 이란?

회색

안드로이드는 NinePatch 그래픽이라고 하는 비트맵 이미지를 지원합니다.  PNG 이미지로 되어있는데 Stretchable(늘어나는) 영역을 정의할 수 있습니다. 이 나인패치 이미지는 보통 뷰(View)의 배경이미지로 사용됩니다. 실제 버튼의 디폴트 배경 이미지가 9 Patch 이미지로 되어있습니다. 

일반 PNG 이미지에서 1pixel의 보더를 가지는 형태로 구성되어있습니다. 이 보더가 늘어나는 영역과 늘어나지 않는 영역을 정의하게 됩니다. 왼쪽과 위쪽의 1 pixel 검은색 선은 늘어날 수 있는 부분을 정의합니다. 늘어날 수 있는 부분은 여러개가 될 수 있습니다. 

오른쪽과 아래쪽의 1 pixel 검은색 선은 뷰가 그려질 영역을 정하는 일을 합니다. 다시 말해 패딩 영역을 결정합니다. 만약 이 선을 그리지 않는다면 왼쪽과 위쪽의 선이 사용됩니다. 예를 들어 텍스트뷰의 경우 그려질 텍스트가 이 선이 그려진 영역안에서 표시됩니다.

나인패치 이미지를 쉽게 만들기 위해서 SDK의 Tools디렉토리에 draw9patch라고 하는 이미지 에디터가 들어있습니다. 아니면 그냥 일반적인 그래픽 에디터에서 그려도 상관없습니다.



파일이름은 반드시 .9.png라고 끝나도록 저장해주어야 합니다. res/drawable/some_name.9.png 와 같은 형태가 되겠지요. 만약 그냥 png라고 끝난다면 일반 이미지 파일로 처리가 됩니다.



예제를 한번 확인해보시지요. 왼쪽의 버튼과 오른쪽의 버튼은 모두 같은 나인패치 Drawable을 백그라운드 이미지로 사용하고 있습니다. 이미지 파일 하나로 다양한 크기의 버튼의 백그라운드로 사용될 수 있다는 것은 정말 편리하고 UI작업을 할 때 항상 사용하는 것이니 알아두시면 좋습니다.

이 게시물을...

 

목록

엮인글 주소 : http://www.androidpub.com/index.php?document_srl=2096&act=trackback&key=c54

2009.05.15 16:01:01

와이드오픈

오호.. 중요한듯한데. 예제. 소스는.없나효?

2009.12.10 17:47:33

늑대왕자

SDK의 Tools 디렉토리에 draw9patch.bat 파일이 있고 이것을 실행하면 아래와 같은 실행창이 나옵니다.
(--; 이미지 추가를 하려는데 기능이 안먹히는 군요. 아무튼...)
실행창에는 딸랑 Open한 아이콘.png 파일이 화면에 나타나고 일반적인 그리기 도구가 없습니다. 
그리기 도구가 없는데 이 프로그램으로 뭘 하는것인지... 도움말도 없고... 
좀 더 이해하기 쉽게 부연설명을 부탁드립니다. (- .-) (_ _) 꾸벅 

2010.03.05 14:34:43

netdiver

1. 실행
2. 일반 png 파일을 열기
3. 아래 Zoom을 조정하여 파일을 모두 볼 수 있게 하기
4. 왼쪽 화면의 가장 자리의 확장 영역을 수정 (왼쪽클릭: 영역 표시, 오른쪽클릭: 영역 삭제, 오른쪽 화면: 확장 샘플)
5. 저장

 

2010.02.11 17:23:15

주노

오아!! 여느 책 보다 훨씬 쉽게 이해됐습니다. ^^ ㄳㄳ

2010.09.29 18:45:22

소망아기

완벽한 설명이네요; 굳~!

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: http://chools.tistory.com/category/Mobile

[펌글] 나인패치 이미지 개념의 이해

 

나인패치 이미지 개념 이해하기

테마관련 포스팅을 하다보니 이전에 포스팅한 데이타가 삭제가 되어있어 이어지지 않아서 9patch(나인패치) 이미지 개념에 대해 새롭게 포스팅 해보려고합니다. 1년전에 포스팅 할 때보다 더 많은 지식이 나름 생겼으니 조금더 체계적으로 알려드릴께요.

 

이 안드로이의 나인패치 이미지는 테마작업을 하는데 정말 고마운 존재이자 까다로운 존재입니다. 하지만 개념만 이해하시면 정말 유용하게 사용할 수 있습니다. 사실 안드로이드의 UI를 구성하는데 있어서 이 "9.png"로 표시되는 이미지 때문에 시스템 용량을 상당히 줄이고 또한 하나의 이미지로 다른부분에도 유용하게 사용할 수 있습니다.

 

안드로이드 계열 테마를 분석해보면 이미지 파일은 크게 PNG, 9.PNG, JGP로 나뉘게 됩니다. 스마트폰으로 사진을 찍게 되면 JPG로 저장이 되지만 테마파일은 배경화면을 제외한 이미지는 PNG입니다. 그럼 왜 하나로 통일하지 않고 나눠서 사용하고 있을까요? 그 이유중에 하는 PNG가 용량이 크지만 트루컬러 지원으로 선명도가 훨신 좋고 배경의 투명을 인식합니다. 그래서 선명한 이미지를 모바일에서 표현하기 위해 우리에게 익숙한 JPG보다는 PNG를 사용하게 되는겁니다.

 

그런데 여기에서 한가지 문제점이 발생합니다. 이미지 용량이 크다.. 이건 모바일 기기에서 너무나 취약한 부분입니다. 한정된 시스템 공간에 고화질의 이미지를 무한대로 넣을 수 없습니다. 그래서 등장한 놈이 나인패치라는 이미지 입니다. 이 나인패치 이미지는 작은 이미지라도 9patch 공간에 스케일을 조절할 수 있는 정보를 넣어줌으로써 외형의 이미지는 깨지지 않고 대형이미지 출력이 가능하게끔 가공된 것 입니다.

JPG라는 이미지는 픽셀에 의해 그 이미지 크기 정해집니다. 가로px * 세로px * (resolution)

그래서 이미지 사이즈 이상으로 키우게 되면 그 이미지는 깨지게 됩니다. 하지만 나인패치 이미지는 용량은 그대로 유지하면서 아무리 확대를 해도 깨지지 않게 이미지를 만들 수 있습니다. (모든 이미지를 나인패치로 만드는 건 아닙니다.)

 

현재 이 나인패치라 이미지는 대표적으로 안드로이드 계열 테마와 카카오홈, 아펙스런처 등 모든 안드로이드 실행화일에 존재합니다. 그리고 가장 대중화 되어있는 카카오톡 테마를 테마봇이나 테마에디터로 만들때도 나인패치가 존재하기 때문에 개념을 알고 계시면 더 좋은 퀄리티의 자료를 만들 수 있습니다.

 

그럼 이런 무한대로 늘어나는 고무줄 같은 이미지들이 어떠한 특징을 갖고 이미지를 통한 정보를 전달하는지에 대해서 알아볼께요^^

(아래 안드로보이 윗쪽 보이지않는 영역에 구간을 설정해서 원하는 부분만 늘려줄 수 있습니다.)

 

 

나인패치 이미지 확인하기

 

그럼 이 나인패치라는 이미지는 어떻게 확인 할까요? 이미지는 7zip으로 압축을 해서도 확인할 수 있고 Apkmanager로 디컴하셔도 확인할 수 있습니다. 단지 7zip으로 압축을 풀면 편집은 불가능하고 이미지 이름에 xxx.9.png라는 파일 이름을 보고 나인패치 이미지 인지 확인을 할 수 있습니다. 하지만 디컴파일하게 되면 이미지를 파일명 뿐아니라 어떤정보가 들어가 이는지 정보까지도 확인이 가능하며 draw9patch 툴이나 포토샵같은 이미지 편집툴로 수정을 하실 수 있습니다. 그럼 7zip으로 압축해제한 파일과 디컴파일한 9패치 이미지들을 확인해 보세요^^

일반적으로 나인패치는 버튼쪽과 타이틀 부분에 많이 들어갑니다. 두이미지 특징이 배경에 이미지가 들어가고 그위에 글씨등이 채워지게 되는 구조인데 나인패치가 가장 많이 들어가 있는 파일중에 하나입니다.

 

framework-res.apk를 7zip으로 압축해제해서 이미지 파일을 확인해봤습니다. 우리가 찾고 있는 이미지위에 정보선은 보이지 않고 파일명으로만 xxx.9.png파일을 확인할 수있습니다. 이상태에서는 나인패치 정보영역을 확인할 수 없습니다. 그럼 apk툴을 이용해서 디컴파일한 파일을 보실까요?

 

 

 

 


 

 

디컴파일하게 되면 이미지 밖에 숨겨저있던 9패치 영역이 공개가 됩니다. 위와는 다르게 이미지 사방으로 검은 선들이 들어가 있는 걸 확인하실 수 있는데요. 이 선의 의미만 알면 저흰 9.patch를 일반 이미지 다루듯이 수정하하실 수 있습니다. 그럼 저 1px의 검은 선의 의미를 알아볼까요??

 

 

 

 

나인패치 외곽 검은 실선의 의미

 

이부분을 예전에는 그려서 많이 설명했는데 해외에 좋은 자료가 있어서 개념정리할 수 있는 글을 첨언해서 설명해 드리겠습니다. 출처:http://radleymarx.com/blog/simple-guide-to-9-patch


 

나인패치 이미지 구조

기본적으로 나인패치 이미지는 두가지 영역으로 나눠지게 됩니다.이미지의 늘어나는 부분을 정해주는 나인패치영역과, 이미지 안에 텍스트등의 내용을 어떤 레이아웃으로 표시해줄지 정의하는 영역입니다.

Scalable area 영역이 이미지를 늘려주는 구간을 설정해 주는 나인패치 영역이고

Fill area가 이미지 위에 어떠한 내용물을 어느 위치에 표시해줄지 정의 해주는 영역입니다.

이 1px의 검정색의 길이와 여백을 이용해서 자신의 늘려주고자 하는 이미지 영역과 표현하고자 하는 텍스트 영역을 지정할 수 있게 되는겁니다.

 

 

 


 

이미지를 보시면 둥근모서리를 취하고 있지요? 이 이미지를 늘리거나 텍스트를 넣거나 할 때 모서리 끝까지 가게 되면 이미지를 벗어나고 저 둥근 모서리 부분까지 나인패치 영역으로 잡혀 있으면 모서리 굴림이 찌그러지게 늘어지겠지요? 그래서 일정여백을 줘서 이미지가늘어나더라도 저부분은 그대로 둬라라는 의미로 여백을 줍니다. 글씨또한 모서리 끝까지 가면 이미지가 짤리니 그부분을 여백으로 둔겁니다.

 

아래 이미지는 Scalable Area의 확대 예를 보여주는 부분입니다.안드로이드 UI에서는 새로모드, 가로모드가 존재하고 또한 팝업이나 일반 화면에서의 버튼크기가 모두 다르게 됩니다. 그러한 이미지를 다 따로만든게 아니고 디자인되는 부분을 여백 처리하고 늘어나는 구간을 정의 함으로써 가로, 세로 어떤 크기로 늘어나도 형태가 깨지지 않는 예를 보여주고 있습니다. (형태가 변해도 둥근모서리 값은 변하지 않습니다.)

 

 

 


 

Fill Area 설명입니다. (좌측,아래측 라인)

들어가는 텍스트, 아이콘등의 여백과 레이아웃을 설정할 수 있습니다. 아래 샘플처럼 버튼크기가 변경되도 정보 표시영역을 나인패치로 잡아둬서 좌우,위아래 여백은 침범하지 않고 이미지 확대축소에 따른 텍스트가 정리되어서 출력되는 모습을 볼 수 있습니다.

 

 

 

 

 

나인패치 이미지의 Scale과 Fill 영역이 상호 어떻게 연관되어서 보여지는 예입니다.

아래 보시면 측면의 둥근 아이콘의 나인패치 지정으로 가로확대 시에도 측면 원이 깨지지 않고 가운대 영역만 늘어나는 이미지를 볼 수 있습니다. 또한 안에 들어가는 아이콘의 위치도 Fill영역에서 지정되어있어서 정돈되 모습을 아이콘이 정렬되는걸 보실 수 있습니다.

 

 

 

 

 

Fill영역없이 이미지에 글씨를 넣어서 Scale영역으로만 늘어나는 모습은 아래와 같습니다.

 

 

 

 

 

 

Fill 영역에 대해 보충설명 해드릴께요. 메세지 말풍선에서 나인패치는 정말 많이 활용됩니다.

 

 

 

 

 

 

 

 

 

 

 

=======================

=======================

=======================

 

 

 

출처: http://bcho.tistory.com/category/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C

 

안드로이드 채팅 UI 만들기 #2 

나인패치 이미지를 이용한 채팅 버블

 

조대협 (http://bcho.tistory.com)

 

지난 글에서는 ListView를 이용하여 스크롤이 가능한 텍스트 기반의 간단한 채팅창을 만들어보았다.

이번글에는 채팅 메세지에 이미지로 채팅 버블을 입히는 방법을 알아보도록 한다.

채팅 버블 이미지를 입히는 방법이나 원리는 간단한데, 채팅 메세지를 출력하는 TextView에 백그라운드이미지를 입혀서 출력하면 된다. 그런데 여기서 문제가 생기는데, 채팅 메세지 버블의 크기는 메세지의 글자수에 따라 가변적으로 변경되기 때문에, 일반적인 이미지를 백그라운드로 넣어서 가로로 늘이거나 줄이게 되면 채팅창이 이상하게 가로로 늘어날 수 가 있다.. (아래 그림에서 가로로 늘렸을때 말꼬리 부분 삼각형이 원본과 다르게 늘어난것을 확인할 수 있다) 

 

 

 

< 원본 이미지 > 

 

 

 

<가로로 늘린 이미지 >

 

 

그래서 필요한 것이, 특정 부분만 늘어나게 하는 것이 필요한데. 이렇게 크기가 변경되어도 특정 구역만 늘어나게 하는 이미지를 나인패치 이미지 (9-patch image라고 한다.). 나인패치 이미지를 이용하여 말풍선을 느리게 되면, 말꼬리 부분은 늘어나지 않고 텍스트가 들어가는 영역만 늘어난다. 

 

 

 

 

< 나인패치 이미지를 가로로 늘린 경우> 

 

나인패치 이미지 만들기

 

나인 패치 이미지는 안드로이드 SDK에 내장된 draw9patch라는 도구를 이용해서 만들 수 있다.

보통 안드로이드 SDK 가 설치된 디렉토리인 ~/sdk/tools 아래 draw9patch라는 이름으로 저장되어 있다.

실행하면 아래와 같은 화면이 뜨는데, 

좌측은 일반 이미지를 나인패치 이미지로 만들기 위해서 늘어나는 영역을 지정하는 부분이고 (작업영역), 우측은 가로, 세로등으로 늘렸을때의 예상 화면 (프리뷰)을 보여주는 화면이다.

 

 

 

 

그러면 9 patch  이미지는 어떻게 정의가 될까? draw9patch에서 가이드 선을 드래그해서 상하좌우 4면에, 가이드 선을 지정할 수 있다.

 

 

 

좌측은 세로로 늘어나는 영역, 상단을 가로로 늘어나는 영역을 정의하고, 우측은 세로로 늘어났을때 늘어나는 부분에 채워지는 이미지를, 하단은 가로로 늘어났을때 채워지는 이미지 영역을 지정한다. 

이렇게 정의된 나인 패치 이미지는 어떻게 사용하는가? 일반 이미지 처럼 사용하면 되고, 크기를 조정하면 앞서 정의한데로, 늘어나는 부분만 늘어나게 된다.

 

나인패치 이미지를 채팅 메세지에 적용하기 

 

그러면 이 나인패치이미지를 앞에서 만든 채팅 리스트 UI에 적용하여 말 풍선을 만들어보도록 하자.

여기서는 채팅 버블을 좌측 우측용 양쪽으로 만들도록 하고, 서버에 연결된 테스트용이기 때문에, 메세지를 입력하면 무조건 좌/우 버블로 번갈아 가면서 출력하도록 한다.

 

앞의 코드 (http://bcho.tistory.com/1058) 에서 별도로 바위는 부분은 ChatMessageAdapter의 getView 메서드만 아래와 같이 수정하고 채팅 버블로 사용할 이미지를 ~/res/drawable/ 디렉토리 아래 저장해 놓으면 된다. 

 

 

 

 

그러면 수정된 getView 메서드를 살펴보도록 하자.

 

   @Override

    public View getView(int position, View convertView, ViewGroup parent) {

        View row = convertView;

        if (row == null) {

            // inflator를 생성하여, chatting_message.xml을 읽어서 View객체로 생성한다.

            LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            row = inflater.inflate(R.layout.chatting_message, parent, false);

        }

 

        // Array List에 들어 있는 채팅 문자열을 읽어

        ChatMessage msg = (ChatMessage) msgs.get(position);

 

        // Inflater를 이용해서 생성한 View에, ChatMessage를 삽입한다.

        TextView msgText = (TextView) row.findViewById(R.id.chatmessage);

        msgText.setText(msg.getMessage());

        msgText.setTextColor(Color.parseColor("#000000"));

 

        // 9 패치 이미지로 채팅 버블을 출력

        msgText.setBackground(this.getContext().getResources().getDrawable( (message_left ? R.drawable.bubble_b : R.drawable.bubble_a )));

 

        // 메세지를 번갈아 가면서 좌측,우측으로 출력

        LinearLayout chatMessageContainer = (LinearLayout)row.findViewById(R.id.chatmessage_container);

        int align;

        if(message_left) {

            align = Gravity.LEFT;

            message_left = false;

        }else{

            align = Gravity.RIGHT;

            message_left=true;

        }

        chatMessageContainer.setGravity(align);

        return row;

 

    }

 

수정 내용은 간단한데, 좌측/우측용 채팅 버블을 출력하는 부분과, 좌측 버블은 좌측 정렬을, 우측 버블은 우측 정렬을 하는 내용이다.

 

채팅 버블을 적용하는 방법은 TextView에서 간단하게 setBackground 메서드를 이용하여 백그라운드 이미지를 나인패치 이미지를 적용하면 된다.

 

msgText.setBackground(this.getContext().getResources().getDrawable( (message_left ? R.drawable.bubble_b : R.drawable.bubble_a )));

 

나인패치이미지가  resource아래 drawable 아래 저장되어 있기 때문에, getResource().getDrawable() 메서드를  이용하여 로딩 한다.

 

        LinearLayout chatMessageContainer = (LinearLayout)row.findViewById(R.id.chatmessage_container);

        int align;

        if(message_left) {

            align = Gravity.LEFT;

            message_left = false;

        }else{

            align = Gravity.RIGHT;

            message_left=true;

        }

        chatMessageContainer.setGravity(align);

 

다음으로는 채팅 버블을 번갈아 가면서 좌/우측에 위치 시켜야 하는데, 채팅 버블의 위치는 채팅 메세지를 담고 있는 LinearLayout을 가지고 온후에, LinearLayout의 Gravity를 좌우로 설정하면 된다.

 

나인패치 이미지를 이용한 완성된 채팅 버블 UI는 다음과 같다. 

 

 

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: http://violetolic.tistory.com/?page=7

 

나인패치란 무엇일까요? 패턴이란 무엇일까요?

 

어플리케이션 디자인을 하다보면 리소스 파일이 수십, 수백개가 만들어집니다.

개발상에서 보면 들어가는 이미지들의 용량이 문제가 되기도 하고, 속도가 문제가 되기도 하고, 디바이스 별 해상도의 차이로 인해 기기별 대응 문제가 생기기도 하지요..

이런 경우 디자인상에서는 또 계속 반복되지만 사이즈가 다 달라지기 때문에 몇 종류의 이미지를 사이즈별로 만들어야하는 경우가 있습니다

너무... 힘들죠..ㅜㅜ

 

특히 제가 작업을 하는 경우 스플레쉬 페이지나 대쉬보드의 배경 이미지라던지, 각 종 리스트 부분에서 이런 문제가 많이 발생합니다. 

많은 용량을 빨리 불러야하는 부분에서 느려지는 문제가 발생하니까요?

 

이럴때를 위한 대응법이 있지요!

바로바로 이미지를 최대한 작게 줄이는 법!!! 여기에 해답이 있습니다.

 

개발코드나 개발용 소스를 통해 간단한 큰 이미지를 쉽게 적은 용량으로 표현할 수 있는데 일정한 반복 패턴이 있는 이미지의 경우 패턴과 나인패치를 통하여 쉽고 공통적인 파일로 대체할 수 있지요!

음, 단점이라면 변화가 큰 이미지의 경우 반복하기 힘들 수 있습니다.

 

뭐냐뭐냐뭐냐,,,,,,바로 패턴과 나인패치랍니다. 

이름을 들어본 사람들은 있으시겠지만 아직 뭐가 뭔지 잘 모르시겠죠? 한번 그 둘을 설명해드릴께요.

 

먼저, 패턴을 설명하겠습니다.

 

*패턴 (pattern)

포토샵에서의 패턴을 적용하는 방식과 동일하게 개발측에서 만들어진 패턴 이미지를 반복을 통하여 이미지를 연장하는 형식입니다.

똑같은 모양의 색종이를 줄줄이 이어붙여서 하나의 패널을 만들어내는 것과 같은 형식이라고 말씀드리면 쉽게 이해될까요?

 

작은 이미지 하나를 하나의 패턴으로 삼아, 개발자에게 주면 전체 화면을 종횡 상관없이 이미지를 반복시켜 화면 하나를 가득 채울수도 원하는 영역만 채울수도 있답니다.

이미지 자체도 작은 이미지고 패턴화하는 크기를 최소화하고 이미지 자체의 용량도 save for web등을 통해 용량을 최소화하 불러오는 속도도 큰 이미지일 때보다 훨씬 빨라지고, 전체 이미지 용량 자체도 많이 줄어요!

 

 

  이런 이미지를 하나의 패턴으로 본다면

 

   

 

이렇게 가로로 주르륵, 세로로 주르륵 연장할 수 있는 방법입니다.

이런 것은 가로 세로 반복을 해도 이미지가 깨져보이지 않는 형태일 때 쓸 수 있어요! 

자르는 폭이나, 높이에 따라 다양한 패턴 효과를 나타낼 수 있어 이미지 용량을 줄이는데 아주 효과적이랍니다^^

나는 가로로 반복을 하되 세로로 그라데이션이 있는 이미지를 반복해 표현하고 싶다?

전 그럴 때가 자주 있어요.

그럴때는 반복이 필요한 사이즈로 높이를 고정한 뒤 반복시키면 오케이!

 

 

 

>>>>>  

 

 

이렇게 패턴을 이용하시면, 전체 이미지를 넣을 때보다 50%이상의 이미지 용량 감소 효과를 볼 수 있답니다^^

만약 이런 형식이 부담된다면 작은이미지를 반복 시킨 후, 개발측에서 그라데이션등을 넣을 수도 있으니 이런 부분은 다음에 또 설명드릴게요^^

 

 

자, 패턴에 대해서는 다들 충분히 이해가 되셨나요?

 

 

그럼 나인패치에 대하여 간단하게 고고고~

 

*나인패치 (nine-patch, 9-patch)

패턴처럼 반복하고 싶지만 변화가 큰 파일들, 예를 들어 높이가 다양하게 변하는 리스트박스라던지 개발에서 만들 수 있는 기본적인 박스 말고 이미지로 꼭 쓰여야하지만 변화가 있는 이미지 블럭의 경우 나인패치를 통하여 작업할 수 있어요.

별다른 작업이 필요한 것은 아닙니다. PNG 파일의 경우일 때 이미지를 나인패치를 할 수 있는 프로그램들을 통해 자동으로 만들수도 있고요, 

뼛속까지 디자이너인 저는 포토샵으로 합니다....하하 뻥이고 프로그램이 없어...ㅜㅜ

쉽게 포토샵에서  할 수 있지요.

이미지파일에서 주변에 1px씩 확장한 후(확장된 1px안에는 절대 나인패치 선 말고 컬러 등이 들어가면 안되요! 들어가면 오류가 똭!!

나인패치 영역을 지정한 뒤 이름을 filename.9.png 이런 형식으로 이름을 변경해서 저장해주시면되요^^

나인패치 하는 법이나 프로그램에 대해선 추후에 더 자세히 설명드릴게요.

 

자, 이게 리스트로 쓸 이미지입니다.

리스트 이미지를 통해 설명을 하자면 아래 이미지의 경우 완전한 나인패치 파일은 아니지만 저는 이렇게 작업을 하고 싶었어요!

 

1. 폭은 유지하되 높이를 조절하고 글자를 강아지 발 옆으로만 넣고싶다 :  (특수해보이긴 하지만 이런 식으로 많이 씁니다. 하드코어하게 키워드리죠!ㅋㅋ)

 

2. 강아지 발이 늘어나지 않게 강아지 발 아래로만 늘어나면서 글자를 늘어나게 넣고 싶다.

 

이렇게 하고 싶었어요! 대신 개발자가 폭을 따로 안맞출 수 있게끔 폭은 이미지 사이즈를 따로 축소하지 않고 그대로 유지하고싶습니다.

하지만 실상은....

 

 

 

 

뜨잉뜨잉....ㅜㅜㅜ 이러면 안되요 개발좌님...ㅠㅠ

이럴때 나인패치가 필요하답니다.

 

그럼, 어떻게 나인패치하면 될까요??

 

 

 

 

이게 바로 나인패치된 파일이랍니다.

이미지의 상하좌우로 아래 작은 검은 점, 선이 보이나요?

 

이 점, 선은 이미지 밖으로 1px씩 이미지를 확장한 공간에 그려지면 됩니다.

그러면 그려진 영역대로 이미지 파일은 늘어나거나 깨지지 않고 오직 저 검은색 점, 선 영역만 주우우우우우욱 늘어나게 됩니다.!

이런 선은 나인패치 프로그램을 통해 할 수도 있고, 포토샵을 통해서도 할 수 있습니다 :-)

 

 

 

좌측과 상단의 점, 선

이미지의 사이즈를 관장하며 저 공통되는 부분이 텍스트나 내부 영역의 변화에 따라 늘어나고 줄어들며 이미지가 확장됩니다.

 

우측과 하단의 점, 선

텍스트의 영역을 나타냅니다. 저 우측과 하단의 공통 영역 안에만 글자가 들어갈 수 있으며 텍스트의 길이에 따라 이미지가 확장이 됩니다.

그래서 이미지가 늘어나는 영역은 분홍색 영역인 것이고,

보라색 영역에 들어가는 텍스트의 양에 따라 좌측과 상단의 분홍색 영역이 늘어나며 축소, 확장될 수 있는 것이죠.

이렇게 된다면 개발바닥 등 이미지나 주변의 스트로크가 늘어나지 않고도, 또 이미지를 다양하게 만들지 않고도 쓸 수 있어요!

 

 

 

이렇게요!!!! 강아지 발이나 스트록의 두께가 변하지 않고 글자가 쏙 들어갔습니다. 이 텍스트의 양은 제한을 두지 않는이상 쭈우우욱 늘어납니다. 쉽게 이해가 되시나요?

 

+ 나인패치 이미지 작업시 최대한으로 작게 해도 됩니다 ㅎ 저는 기본 사이즈를 유지하기 위해 이렇게 했는데 더 줄여도 됩니다 :-) 아래처럼 하고 가이드로 폭 높이 지정해줘도 된다는 말! 상황에 따라 이렇게 하는게 더 편할 수도 있고 불편할 수도 있으니 개발자와 상의하는 것도 좋아요!

 

여러분께 최대한 쉽게 다양하게 이해시켜드릴 수 있도록 썼는데 다들 이해가 잘 되셨나요

추가적인 설명이 있다면 추가하고 궁금한 문의사항에 대하여도 추가가 필요할 부분에 대해 계속 피드백할게요^^

궁금한 점이 있으시면 언제라도 댓글로 문의주세요^^

 

그럼 해버굿데이:-) 빠잉~

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: http://www.androidside.com/bbs/board.php?bo_table=b49&wr_id=147861

카카오톡 같은앱만들때
말풍선 은 어떻게만드나요?
텍스트뷰를 커스터마이징 해야되나요?
말풍선관련 예제나 강좌 같은것있으면
도움바랍니다

 

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

나인패치로 만든 말풍선 이미지를 텍스트뷰의 배경으로 사용하심 됩니다.

http://distress.tistory.com/49

http://bbulog.tistory.com/entry/xml-%ED%8C%8C%EC%9D%BC%EB%A1%9C-%EB%A7%90%ED%92%8D%EC%84%A0-%EB%A7%8C%EB%93%A4%EA%B8%B0

참고해보세요

 

 

 

=======================

=======================

=======================

 

 

 

반응형

 

 

728x90

 

 

 

 

출처: http://bbulog.tistory.com/entry/xml-%ED%8C%8C%EC%9D%BC%EB%A1%9C-%EB%A7%90%ED%92%8D%EC%84%A0-%EB%A7%8C%EB%93%A4%EA%B8%B0

xml 파일로 말풍선 만들기

 

안드로이드에서 배경을 처리하기 위해서, 이미지나 컬러를 많이 사용한다.

그리고, res/drawable 폴더에 xml 파일을 만들어서 이미지처럼 사용할 수 도 있다.

 

이번 포스팅에서는 xml 파일 만을 이용하여, 아래와 같은 모양의 말풍선 layout 을 만들어보겠다.

 

 

 

 

화살표가 아래를 향하는 말풍선 구조는 이렇다.

<LinearLayout android:orientation="vertical"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="10dip"

android:clickable="true" >

<FrameLayout android:src="@drawable/speech_box"

android:layout_width="match_parent"

android:layout_height="100dip">

</FrameLayout>

<ImageView android:src="@drawable/down_arrow_nor"

android:layout_width="30dip"

android:layout_height="30dip"

android:layout_gravity="center_horizontal" />

</LinearLayout>

그림으로 보면 이런 구조

 

 

 

좌우, 위로 향하는 화살표 말풍선은 잘 배치하면 된다.

말풍선 안에 단순 텍스트 뿐 아니라 이미지를 배치하거나 다른 레이아웃, 뷰를 쉽게 추가하기 위해서, 말풍선 바디 부분은 FrameLayout 을 사용했다.

 

사실 이 글에서 다루고 싶었던 내용은 삼각형 모양의 화살표를 xml 파일로 만드는 것이다.

알고보면 원리는 간단하다.

사각형을 그린 뒤, 45도 회전시킨 후, x, y 축으로 적당히 이동시켜서, 한쪽 모서리만 그려지게 만들면 된다.

 

아래로 향하는 화살표를 만들기 위해, drawable 폴더에 down_arrow_nor.xml 파일을 하나 만들어서 아래와 같이 사각형을 그려주도록 하자.

<?xml version="1.0" encoding="utf-8"?>

 

<item>

<shape android:shape="rectangle" >

<solid android:color="#88FFFFFF"/>

<padding 

android:left="0dip"

android:right="0dip"

android:top="0dip"

android:bottom="0dip"/>

</shape>

</item>

</layer-list>

레이아웃에 이미지뷰를 띄워서 확인해보면 아래 그림과 같이 사각형이 그려진다. (배경 컬러 : #555500)

 

 

 

이제 이 사각형을 오른쪽으로 45도 돌려주면 아래와 같이 8각형 모양으로 나타난다. 이는 내가 이미지뷰에 지정한 사이즈 (50dip x 50dip) 의 영역 밖에서 각 모서리 부분이 그려졌기 때문이다.

 

 

<?xml version="1.0" encoding="utf-8"?>

 

<item>

<rotate android:fromDegrees="45"

android:toDegrees="45">

<shape android:shape="rectangle" >

<solid android:color="#88FFFFFF"/>

<padding 

android:left="0dip"

android:right="0dip"

android:top="0dip"

android:bottom="0dip"/>

</shape>

</rotate>

</item>

</layer-list>

이제 모서리 부분만 보이도록 이미지를 X, Y 축 방향으로 적당히 이동하면 된다.

그런데 여기서 주의할 점은, 이미지 회전 시 X,Y 축도 같이 45도 틀어졌다는 것이다.

그래서, X 축 방향으로만, 혹은 Y 축 방향으로만 움직인다고 해서 모서리만 보이거나 하지 않는다. 두 축에 대해 모두 이동을 해야 한다.

 

 

 

여러번 해보면서 자신이 생각하는 모양에 맞게 맞춰나가는게 좋다.

내가 사용한 값은 이렇다.

<?xml version="1.0" encoding="utf-8"?>

 

<item>

<rotate

android:fromDegrees="45"

android:toDegrees="45"

android:pivotX="135%"

android:pivotY="13%" >

<shape android:shape="rectangle" >

<solid android:color="#88FFFFFF"/>

<padding 

android:left="0dip"

android:right="0dip"

android:top="0dip"

android:bottom="0dip"/>

</shape>

</rotate>

</item>

</layer-list>

 

 

 

=======================

=======================

=======================

 

 

 

 

 

출처: http://distress.tistory.com/49

안드로이드에서 말풍선을 그려보자.

 

 

안펍에서 누군가 질문을 했다. PicSay 에 있는 말풍선이 비트맵은 아닌것 같은데 이걸 우째 그리냐고... 그게 이거다.

일부러 까만색으로 동그라미 그렸다. 우째 그리는지 감이 좀 오시는가..??

 

 

 

drawOval 로 굵은선있는 동그리마 주르르르륵 그린뒤 하얀칠한 동그라미 안쪽에 덮어씌워 그리면 된다고 답했는데 잘 못알아 들으신다.

역시 이런건 말로 설명하기가 쉽지가 않다.. 그래서 밥먹고 와서 짬나는 시간에 후다닥 만들었다. 잼있어 보여서... =_=;;

만들었으니 포스팅도 해야지 ㅡㅡ;;;

 

원리는 간단하다.  타원의 둘레를 따라 작은 타원 둥글둥글 그리고...안을 싹 칠하고..

가운데 타원의 둘레를 따라 x, y 좌표는 아래 그림처럼 구하면 된다.

중고딩때 수학시간에 열심히 졸았어도 지금 프로그램 해서 밥먹고 살겠다고 하는사람들이라면 그림보면 대충 이해는 갈거라 믿는다.

 

 

 

 

이 그림에 태클금지. 이만큼 그리는것도 오지게 힘들었다.

내부 타원의 둘레를 따라 x, y 값을 구한다음 거기 또 작은 타원을 그려준다. 이런식으로 36도씩 10개를 그렸다.

선을 굵게해서 그리면 나중에 내부를 칠할때 굵게그렸던 선은 반이 지워지게 된다.

선을 다 그리고 나면 똑같은 좌표 똑같은 크기로 이번엔 외곽선이 없고 흰색으로 내부가 채워지는 그림을 한번 더 그리자.

이걸 반투명으로 보면 아래 그림의 왼쪽처럼 되는것이다. 뜯어 고치는건 알아서들 하시고... 나도 짬나면 언제 한번 크기조절 이동해서 배경 비트맵이랑 짬뽕도 해주는녀석을 만들어 봐야겠다.

 

기본원리야 어느동네 어느 프로그램언어로도 비슷비슷 할것이다. 하지만 이것을 뜯어 고쳐서 사용하시려는 분들은 최소한 댓글을 적으시라!!!

반투명으로 보면 이런구조다.

 

이것이 완성한 화면.

 

 

 

=======================

=======================

=======================

 

 

 

카카오톡처럼 Text를 말풍선 안에 넣고 싶습니다.

 

카카오톡처럼 Text를 말풍선 안에 넣고 싶습니다.

Text를 받아오면 그 Text의 길이에 맞춰

말풍선이 늘어났다 줄어났다 하는 그런 기능을 구현하고 싶습니다.

 

좋은 아이디어나 

소스 있으신 고수님들 부탁드립니다! 

 

----------

건방진프로그래머

(추천: 1 / 0)

그건 나인패치를 이용해서 해당 영역만큼 이미지를 늘린겁니다.. 말풍성은 다 그렇게 해요

2012.09.15 00:21:17

우랑촹촹쾅

감사합니다! 해결 했습니다! 의외로 엄청 간단하네요!!

 

 

 

=======================

=======================

=======================

 

 

 

출처: http://www.androidside.com/bbs/board.php?bo_table=B49&wr_id=43900

[안드로이드] layout과 UI배치에 관한 질문입니다...ㅜㅜ

제가 채팅어플을 만들라고 하느데.. 카카오톡과 비슷한 UI로 일단 가고 있는데 안되는데 있어서 질문을 드립니다.

일단 왼쪽그림과 같이 화면을 구성 했느데.. 여기서 문제가 밑에 edittext에 글씨를 쓰기 위해서 터치를 하면 오른쪽과 샅이 키보드만 올라오네요..ㅠㅠ 전 매끝에 그림처럼 하고 싶은데.. 안되네요...ㅍㅠㅠ 어떻게 해야할까요?!

 

  

 

  

 

 

혹시나 해서 XML부분도 올립니다... 잘못 설정을 했거나 이상한게 또는 다른 방법이 있으면 좀 알려주세여.ㅠㅠ

 

========== XML 소스 ===========================

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<LinearLayout 
 android:layout_width="fill_parent" 
 android:id="@+id/im1"
 android:layout_height="517dp">
<FrameLayout 
 android:layout_width="fill_parent"
 android:layout_height="wrap_content">
<ImageView 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:scaleType="fitXY"
 android:src="@drawable/i6"/>
<ListView
    android:id="@+id/android:list"
    android:listSelector="#00000000"
    android:cacheColorHint="#00000000"
    android:divider="#000000"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"/>

</FrameLayout>
</LinearLayout>

<LinearLayout 
 android:layout_width="fill_parent" 
 android:layout_height="wrap_content"
 android:background="#2F4F4F"
 android:layout_below="@id/im1"
 android:orientation="horizontal">
<TextView 
 android:layout_width="20dp" 
 android:layout_height="wrap_content" 
 />
<EditText 
 android:hint="메세지를 입력하세요"
 android:id="@+id/editText1"
 android:inputType="textMultiLine"
 android:maxLines="4"
 android:layout_width="200dp" 
 android:layout_height="wrap_content"/>
<Button 
 android:text="전 송" 
 android:id="@+id/button1" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content"/>
 
</LinearLayout> 
</LinearLayout>

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

액티비티 속성에  android:windowSoftInputMode="adjustResize" 넣어주시면 됩니다.

 

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: http://www.androidside.com/bbs/board.php?bo_table=B49&wr_id=126524

 

안녕하세요

다름이 아니라 카카오톡 채팅 UI와 유사한 작업을 하고 있습니다.

카카오톡 채팅 화면을 보면 하루 간격으로 그날 맨 처음 온 메시지 위에만 날짜 layout 이 생성되는 기능을 구현하고 싶은데 오늘 하루종일 삽질만 하다가 새벽을 넘겨버렸네요.

 

제가 작업중인 서버에서 내려주는 dateformat 형식은 yyyy-MM-dd HH:mm:ss 에요.

public class TestDate {
	
	Date currentDate;
	Date pastDate;
	
	// 현재 날짜와 비교
	public long diffOfDate(String current, String past) throws Exception{
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		
		currentDate = formatter.parse(current);
		pastDate = formatter.parse(past);
		
		long diff = currentDate.getTime() - pastDate.getTime();
		long diffDays = diff / (24 * 60 * 60 * 1000);
		
		return diffDays;
	}
	
	public static void main(String[] ar) throws Exception{
		
		TestDate mClass = new TestDate();
		
		ArrayList<String> mDataList = new ArrayList<String>();
		// 추후 비교할때 사용할 데이터
		ArrayList<String> mAddList = new ArrayList<String>();
		
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date today = new Date();
		String mCurrentDate = formatter.format(today);
		
		//오늘
		mDataList.add("2013-09-10 11:10:10");
		mDataList.add("2013-09-10 13:10:10");
		mDataList.add("2013-09-10 10:10:10");
		
		//어제
		mDataList.add("2013-09-09 01:10:10");
		mDataList.add("2013-09-09 14:10:10");
		mDataList.add("2013-09-09 11:10:10");
		mDataList.add("2013-09-09 02:10:10");
		
		//2013-09-08
		mDataList.add("2013-09-08 11:10:10");
		mDataList.add("2013-09-08 12:10:10");
		mDataList.add("2013-09-08 13:10:10");
		
		//2013-09-05
		mDataList.add("2013-09-05 11:10:10");
		mDataList.add("2013-09-05 12:10:10");
		mDataList.add("2013-09-05 13:10:10");
		
		for(int i=0; i<mDataList.size(); ++i){
			long diffDay = mClass.diffOfDate(mCurrentDate, mDataList.get(i));
			if(diffDay > 0){
				mAddList.add(mDataList.get(i));
			}
		}		
	}
	
}

위 코드는 임시 테스트 코드인데 날짜 비교까지는 할 수 있는데 그날 맨 처음 온 메시지는 알 수 없네요.

아래 코드보다 좀더 효율적인 방법을 지도해주시면 감사하겠습니다.

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

메세지마다 read 라는 멤버변수를 둬서 boolean으로 읽을때마다 true를 두시면 false로 되어있는 가장 옛날 메세지가 최근메세지입니당

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

저도 비슷한 문제가 잇었는데..

저는 정렬을 이용하고 날짜 비교를 했습니다.

날짜를 그날 12시 정각으로 설정해놓고, 정렬을 이용하면 하나만 걸러낼 수 있어요.

그리고 요일이 바뀌면 똑같은 작업 해주면 되구요...

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

채팅이라 하시기에 서버는 기본적으로 있다 가정하고 말씀드리면

저같은 경우는 서버에서 받아오는 값을 하루 단위 또는 시간단위로 받아왔습니다. 

위로 스크롤해서 제일위에 닿으면 바로전날의 데이터를 받아와 뿌려주고요...

좀더 간단히 설명을 하면

처음 화면을 열면 채팅한 이력중에 제일 최근꺼를 서버에서 받아와 뿌려줍니다. 

뿌려줄때 위에 님이 원하시는 날짜햇더를 추가 하면 되겠지요.

여기서 일단위로 할건지 줄단위로 시간단위든 10시간 단위든  정하면 됩니다.

일일이 시간 비교하는것 보다는 편하고 부하도 덜할꺼라 생각이 듭니다. 

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

서버에서 데이터를 가져올때 우선 맨 마지막 메시지(최근)를 기준으로 20개를 가져와요.

그 후 스크롤을 올리면 맨 상단에 더보기 버튼이 있구요.

더보기 버튼을 누르면 리스트의 맨 첫번째 메시지를 기준으로 20개를 가져오는 방식이에요.

 

기본적으로 날짜View 는 Gone 처리를 한 상태고, 그날 맨처음 메시지일 경우에만 Visible 처리하면 되는데... 그날 맨처음 메시지를 구하는 방법이 쉽지가 않네요;

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

어플단에서 처리및 비교는 위의 분들이 말씀하신것을 잘생각하면 될것 같습니다.

전 서버에서 처리 하였기에  

메시지를 상대방에게 보낼때 그날 서버시간 기준으로 DB에 처음인지 두번째등록 인지 체크를 한다음

DB에 플래그를 하나두어 처음 저장된 메시지에 만 플래그를 붙여 

어플단에서 체크하는 방법을 사용 하였습니다. 

그러면 어플에서 특별히 시간 체크는 필요없고 플래그 체크후 그시간을 Visivle하면 됬었습니다. 

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

연지우님 말씀대로 서버에서 Flag 데이터 넘겨주도록 처리하여 깔끔하게 처리했네요.

소스상에서 Date 처리하게되면 불필요한 for문이 많아져서 서버에서 처리하는게 가장 깔끔하네요.

도움주셔서 감사합니다

 

 

=======================

=======================

=======================

 

 

 

 

출처:http://www.androidpub.com/index.php?mid=android_dev_qna&listStyle=webzine&sort_index=voted_count&order_type=desc&category=109120&page=27&document_srl=2410816

 

GCM을 이용한 채팅 어플리케이션을 개발중에 있습니다.

현재 채팅방 ui는 simple cursor adapter로 구현되어있으며, 카카오톡과 같은 채팅 어플리케이션과 다르게 리스트뷰 방식으로 구현이 되어져 있습니다.

 

 

 

 

이러한 방식으로 구현되어져 있습니다.

 

카카오톡이나 안드로이드 4.0 기본 문자 어플리케이션처럼, 대화의 내용을 송신/발신자 구분을 두어서 좌우 배치를 하고 싶은데 어떻게 구현을 해야 할 지 감이 오지 않습니다.

 

심플 커서아답터를 싹 갈아엎고 커스텀으로 구현을 해야하는지 어쩐지 길이 보이지 않습니다. 많은 분들의 도움 부탁드립니다. 감사합니다.

 

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

 

단순한 저의 생각으론 카톡같은 ui를 원하신다면 커스텀으루 가시는게 좋지 않을까요?

대화내용 정보에 send 메시지인지 receive 메시지인지 정보를 넣어두고...

getView 에서 왼쪽 정렬, 오른쪽 정렬 정도만 해줘도 충분히 직관적인 ui구현이 가능할 것 같습니다.

 

2012.12.28 16:16:19

레모나씨

역시 방법은 커스텀밖에 없으려나요 ㅠㅠ

답글 감사합니다 ㅠㅠ

2012.12.28 18:54:35

레모나씨

http://www.androidpub.com/1993481

검색을 하고 해당 방법을 이용하여 해결했습니다 ^^;;

검색을 더 열심히 해볼걸 그랬네요, 도움주신 분들께 감사드립니다.

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: http://www.androidpub.com/1993481

CursorAdapter와 ListView ... 리스트 뷰의 모양 바꾸기에 관해서...

 

밑에 밑에 질문 올렸던 사람인데요,,,

밑에 글에 마저 글을 이어 붙이자면,

newVIew() 메서드에서 View 자체를 리턴한 다음에 bindView() 에서 거기있는 VIew 객체에서 TextView들을 찾아 텍스트들을 뿌려주는거라서

 

bindView()에서 조건을 걸어서 레이아웃 자체를 바꿀 수 없다는걸 알았습니다 ㅜ ㅜ

이렇게 생각하는게 잘못된건지도,,, 맞는건지도 사실 잘 모르겠지만...

그래서 질문을 바꿔 올리려고 합니다.

 

제가 채팅 어플을 만들어 보려고 하는데,

채팅 리스트가 listView로 되어 있고, DB에 있는 정보를 뿌려주는 어댑터로는 CursorAdapter를 이용했습니다.

레이아웃은, 상대방이 말하는 때와 제가 말하는 때를 두가지 xml로 작업해둿구요.

 

DB에서 말한 사람을 찾아서 , 그게 나라면 내가말한 레이아웃을. 그게 상대방이라면 상대방의 레이아웃을 보여주고 싶습니다.

그래서 지금 문제되는 것이, newView()에서.. View를 한번 리턴하고 끝나고 리스트에 뿌려주는건 bindView()가 하기 때문에...

중간에 View값을 바꿀 수 없다는 것입니다.ㅜ ㅜ ( 쓰면서 이게 맞는 소린지도 잘 모르겠어요 )

 

그래서 결론적으로 질문드리는 것이...  두가지의 레이아웃을 가진 xml 이 있고, CursorAdapter를 이용해서

레이아웃이 상황에 따라 바뀌면서 리스트뷰가 뿌려지려면 어떻게 해야 하나요...  ( 카카오톡 같이 )

ㅜ ㅜ  흐긍흐긍

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

 

내가 살면서 자답을 달게 되다니 ㅜ ㅜ 무한 감동 감격, ㅋㅋㅋㅋㅋㅋㅋ

아... 어떻게 해결했냐면요 !

두개 레이아웃을 하나로 합쳐서. 프레임 레이아웃으로 만들었어요.

두개 레이아웃이 겹치도록 !

그리고 ~ visible, invisible 을 줘서 ㅜ ㅜ 했더니 잘 되네요. 너무 행복해요. 

혹시나 누가 이걸 보면 참고 할 수 있도록 소스도 !!!!

// newView는 새로운 View 추가시에 어떤 layout을 구성할 것인지 결정
public View newView(Context context, Cursor cursor, ViewGroup parent) {

    inflater = LayoutInflater.from(context);

    this.parent = parent;

    view = inflater.inflate(R.layout.talk_layout, parent, false);

    return view;

}

// 데이터 셋 하나 하나를 처리하는 것을 결정

public void bindView(View view, Context context, Cursor cursor) {

    // 메시지 처리

    String msg = cursor.getString(cursor.getColumnIndex(Constants.TABLE_CONVERSATION_FIELD_MSG));

    // 날짜 처리

    Date temp = new Date(cursor.getLong(cursor.getColumnIndex(Constants.TABLE_CONVERSATION_FIELD_DATE)));

    String date = df.format(temp.getTime());

    // 말하는 인간 누군

    who = cursor.getString(cursor.getColumnIndex(Constants.TABLE_CONVERSATION_FIELD_FROM));

    ll1 = (LinearLayout) view.findViewById(R.id.i_talk);

    ll2 = (LinearLayout) view.findViewById(R.id.friend_talk);

    if (who.equals("me")) {

        ll1.setVisibility(View.VISIBLE);

        ll2.setVisibility(View.INVISIBLE);

        textSay1 = (TextView) view.findViewById(R.id.i_says);

        textDate1 = (TextView) view.findViewById(R.id.i_date);

        textSay1.setText(msg);

        textDate1.setText(date);

    } else {

        ll2.setVisibility(View.VISIBLE);

        ll1.setVisibility(View.INVISIBLE);

        textSay2 = (TextView) view.findViewById(R.id.friend_says);

        textDate2 = (TextView) view.findViewById(R.id.friend_date);

        textSay2.setText(msg);

        textDate2.setText(date);

    }

    Log.v(MY_TAG, "who ? : " + who);

}

}

거북Ol

방법에 좀 차이가 있긴한데 BaseAdapter 에서 구성하는게 더 맞는게 아닌가 싶네요^^;

아래 예제 올려놓은데 링크해둬요~

 http://www.tipssoft.com/bulletin/tb.php/update/1470 

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: http://warmz.tistory.com/573


기존의 카카오톡이나 마이피플과 같은 앱의 채팅방을 자세히 살펴보면 아래와 같다.

 

 

 

가상 키보드가 올라옴과 동시에 리스트뷰의 크기가 그만큼 줄어든다. 즉, 동적으로 리스트뷰의 크기가 변한다는 뜻이다.
리스트뷰를 구현하는 XML 소스에서 이 리스트뷰의 크기를 정적으로 고정시켜주면 안되고 동적으로 높이를 부여해야한다.

그 방법이 바로 android:layout_weight를 이용하는 것이다. android:layout_weight는 해당 위젯에 가중치(높이나 너비)를 주는 옵션인데
LinearLayout(Horizon)에서 EditText와 Button을 각각 layout_width를 0px로 하고 layout_weight를 8, 2 씩 가중치를 주면 너비가 8:2로 적용된다. 이것을 활용하면 위와 같은 채팅방 GUI를 구현할 수 있게 된다.


main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:background="#ffffff">
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="wrap_content" android:background="#123456">
        <ImageView android:src="@drawable/icon"
            android:layout_height="wrap_content" android:layout_width="wrap_content"
            android:id="@+id/imageView1" />
    </LinearLayout>
    <ListView android:layout_height="0px" android:layout_width="fill_parent"
        android:background="#000000" android:id="@+id/lvMessageList"
        android:transcriptMode="alwaysScroll" android:layout_weight="1" />
    <LinearLayout android:orientation="horizontal"
        android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:gravity="center">
        <EditText android:layout_height="wrap_content" android:id="@+id/etMessageForm"
            android:layout_weight="1" android:layout_width="0px" />
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:text="보내기 "
            android:id="@+id/btMessageSend" />
    </LinearLayout>
</LinearLayout>


상단의 LinearLayout에는 layout_height="wrap_content" 를 주는 것과 동시에 이미지뷰를 넣어 높이를 고정시키고 중단의 ListView에는 layout_height="0px"를 주는 것과 동시에 layout_weight="1" 을 부여하여 나머지 면적을 강제로 차지하게 해준다. 하단의 LinearLayout에는 layout_height="wrap_content" 를 주는 것과 동시에 각종 위젯을 넣어 높이를 고정시킨다.

 


가상 키보드가 올라오는 것과 상관없이 리스트뷰의 위치는 고정이되 높이만 동적으로 변하게 된다.

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: http://nsstbg.tistory.com/33

[Android][Ex]채팅 어플리케이션 메인화면 UI 구성

 

Ex.Chat_V1R0.zip
0.99MB

 

카카오톡, 마이피플, 라인, 챗온 등등 여러 채팅프로그램이 서로 매우 유사한 UI 구성을 가지고 있습니다. 

GridLayout과 Listview를 이용하여 기존 채팅 App의 UI를 구성해보았습니다.

 

                

 

 

  

개발 환경

 OS: Windows 7 Professional
 IDE: Eclipse Juno


 -Target Version-
    min: 4.0
    max: 4.2

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/LinearLayout1"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical"
   tools:context=".MainActivity" > 
    <GridLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="center"
       android:numColumns="4" > 
        <ImageButton
           android:id="@+id/btn_friend"
           android:layout_gravity="left"
           android:src="@drawable/ic_launcher" /> 
        <ImageButton
           android:id="@+id/btn_study"
           android:layout_gravity="left"
           android:src="@drawable/ic_launcher" /> 
        <ImageButton
           android:id="@+id/btn_add"
           android:layout_gravity="left"
           android:src="@drawable/ic_launcher" /> 
        <ImageButton
           android:id="@+id/btn_more"
           android:layout_gravity="left"
           android:src="@drawable/ic_launcher" />
    </GridLayout> 
    <FrameLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content" >
 
        <ListView
           android:id="@+id/list1"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           >
        </ListView> 
        <ListView
           android:id="@+id/list2"
           android:layout_width="match_parent"
           android:layout_height="wrap_content" >
        </ListView> 
        <ListView
           android:id="@+id/list3"
           android:layout_width="match_parent"
           android:layout_height="wrap_content" >
        </ListView> 
        <GridView
           android:id="@+id/gview_more"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:numColumns="3" >
        </GridView>
    </FrameLayout> 
</LinearLayout>


출처: https://202psj.tistory.com/777 [알레폰드의 IT 이모저모]

- activity_main.xml에 추가한 ListView의 id는 android:id="@+id/XXXX개발자가 마음대로 정하면 됩니다. 저의 경우 list1list2list3이라고 정했습니다.

 

MainActivity.java

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ListView;
 
public class MainActivity extends Activity implements View.OnClickListener {
 
    private String[] friend = { "HM", "JM", "SK", "DS",
            "EF", "HG", "SD", "QA", "AS",
            "TY", "FG", "QM" };
    private String[] chat = { "1", "2", "3", "4", "5", "6", "7", "8", "9",
            "10", "11", "12", "13" };
    private String[] add = { "?", "??", "???", "????", "?", "??0", "???",
            "????" };
    private String[] more = { "Option", "Profile", "Nothing", "oh", "Game",
            "Demo" };
 
    ListView lViewFriend;
    ListView lViewStudy;
    ListView lViewAdd;
    GridView gViewMore;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        findViewById(R.id.btn_friend).setOnClickListener(this);
        findViewById(R.id.btn_study).setOnClickListener(this);
        findViewById(R.id.btn_add).setOnClickListener(this);
        findViewById(R.id.btn_more).setOnClickListener(this);
 
        lViewFriend = (ListView) findViewById(R.id.list1);
        lViewFriend.setVisibility(View.VISIBLE);
        lViewFriend.setAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, friend));
        lViewStudy = (ListView) findViewById(R.id.list2);
        lViewAdd = (ListView) findViewById(R.id.list3);
        gViewMore = (GridView) findViewById(R.id.gview_more);
    }
 
    @Override
    public void onClick(View v) {
        lViewFriend.setVisibility(View.INVISIBLE);
        lViewStudy.setVisibility(View.INVISIBLE);
        lViewAdd.setVisibility(View.INVISIBLE);
        gViewMore.setVisibility(View.INVISIBLE);
 
        if (v.getId() == R.id.btn_friend) {
            lViewFriend.setVisibility(View.VISIBLE);
            lViewFriend.setAdapter(new ArrayAdapter<String>(this,
                    android.R.layout.simple_list_item_1, friend));
        }
        if (v.getId() == R.id.btn_study) {
            lViewStudy.setVisibility(View.VISIBLE);
            lViewStudy.setAdapter(new ArrayAdapter<String>(this,
                    android.R.layout.simple_list_item_1, chat));
        }
        if (v.getId() == R.id.btn_add) {
            lViewAdd.setVisibility(View.VISIBLE);
            lViewAdd.setAdapter(new ArrayAdapter<String>(this,
                    android.R.layout.simple_list_item_1, add));
        }
        if (v.getId() == R.id.btn_more) {
            gViewMore.setVisibility(View.VISIBLE);
            gViewMore.setAdapter(new ArrayAdapter<String>(this,
                    android.R.layout.simple_list_item_1, more));
        }
    }
}

 

 

=======================

=======================

=======================

 

 

 

채팅 UI 추천 링크:

 http://www.tipssoft.com/bulletin/tb.php/update/1470 

 

 

 

=======================

=======================

=======================

 

 

 

 

반응형


관련글 더보기

댓글 영역