안드로이드 > listview - 채팅 UI 예제
카톡 같은 list 만들기는 카톡의 대화 내역처럼 나오도록 만드는 예제입니다.
custom list를 만들줄 알아야 하고 custom list에서 배경을 나인 패치를 사용하면 됩니다.
custom list를 만들려면 리스트로 사용할 xml을 준비해야 하는데요
아래와 같이 준비하였습니다.
핵심은 양쪽에 view를 두고 가운데 텍스트 뷰를 하나 둡니다.
view의 layout_weight를 각각1로 두고 사용안하는쪽을 GONE 처리 하면됩니다.
viewLeft.setVisibility(View.GONE);
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:orientation="horizontal"
android:id="@+id/layout"
android:gravity="center">
<View android:layout_width="wrap_content"
android:layout_height="1dp"
android:id="@+id/imageViewleft"
android:background="#888888"
android:layout_weight="1"
android:layout_margin="10dp" />
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:text ="text" />
<View android:layout_width="wrap_content"
android:layout_height="1dp"
android:id="@+id/imageViewright"
android:background="#888888"
android:layout_weight="1"
android:layout_margin="10dp" />
</LinearLayout>
리스트에 아이템을 추가할때에는 인자를 하나 더 둬서 오른쪽 왼쪽 어디에 둘건지를 결정합니다.
카톡에 보면 시간 변경선이 나오는 경우가 있는데 여기서는 2번 해당 경우 처리입니다.
View에 layout_height = 1dp로 설정하고 background색을 검은색으로 처리합니다.
- 리스트에 추가할때
m_Adapter.add("처음",0);
m_Adapter.add("이건 뭐지",1);
m_Adapter.add("대화창이다",0);
m_Adapter.add("2015/10/8",2);
m_Adapter.add("쿨쿨",1);
m_Adapter.add("쿨쿨쿨쿨",0);
m_Adapter.add("재미있게",1);
- type에 따른 처리
if( m_List.get(position).type == 0 ) {
text.setBackgroundResource(R.drawable.inbox2);
layout.setGravity(Gravity.LEFT);
viewRight.setVisibility(View.GONE);
viewLeft.setVisibility(View.GONE);
}else if(m_List.get(position).type == 1){
text.setBackgroundResource(R.drawable.outbox2);
layout.setGravity(Gravity.RIGHT);
viewRight.setVisibility(View.GONE);
viewLeft.setVisibility(View.GONE);
}else if(m_List.get(position).type == 2){
layout.setGravity(Gravity.CENTER);
viewRight.setVisibility(View.VISIBLE);
viewLeft.setVisibility(View.VISIBLE);
}
- 동작화면
이제부터 만드는 방법을 상세하게 알아보도록 하겠습니다.
1. 챗 백그라운드 이미지를 만듭니다. (나인패치)
res/drawable 폴더를 만들고 아래이미지 3개를 복사해 넣습니다.
inbox2.9.png (입력메세지1 배경이미지)
outbox2.9.png (입력메세지2 배경이미지)
datebg.9.png (날짜 메세지 배경이미지)
2. activity_chatitem 만듭니다. (레이아웃)
layout/activity_chatitem.xml 내용입니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:orientation="horizontal"
android:id="@+id/layout"
android:gravity="center">
<View android:layout_width="wrap_content"
android:layout_height="1dp"
android:id="@+id/imageViewleft"
android:background="#888888"
android:layout_weight="1"
android:layout_margin="10dp" />
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:text ="text" />
<View android:layout_width="wrap_content"
android:layout_height="1dp"
android:id="@+id/imageViewright"
android:background="#888888"
android:layout_weight="1"
android:layout_margin="10dp" />
</LinearLayout>
3. activity_main 만듭니다. (레이아웃)
layout/activity_main.xml 내용입니다.
채팅을 입력할 수 있는 EditText, Button 등의 위젯이 들어있는 Layout 이며 위에서 만든 custom listview를 포함시킬 Layout 입니다.
<?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="wrap_content"
android:layout_weight="1"
>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ListView
android:id="@+id/listView1"
android:listSelector="#00000000"
android:cacheColorHint="#00000000"
android:divider="#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:transcriptMode="alwaysScroll"/>
</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:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="전 송" />
</LinearLayout>
</LinearLayout>
3. MainActivity.java 만듭니다.
public class MainActivity extends Activity {
ListView m_ListView;
CustomAdapter m_Adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 커스텀 어댑터 생성
m_Adapter = new CustomAdapter();
// Xml에서 추가한 ListView 연결
m_ListView = (ListView) findViewById(R.id.listView1);
// ListView에 어댑터 연결
m_ListView.setAdapter(m_Adapter);
m_Adapter.add("이건 뭐지",1);
m_Adapter.add("쿨쿨",1);
m_Adapter.add("쿨쿨쿨쿨",0);
m_Adapter.add("재미있게",1);
m_Adapter.add("놀자라구나힐힐 감사합니다. 동해물과 백두산이 마르고 닳도록 놀자 놀자 우리 놀자",1);
m_Adapter.add("재미있게",1);
m_Adapter.add("재미있게",0);
m_Adapter.add("2015/11/20",2);
m_Adapter.add("재미있게",1);
m_Adapter.add("재미있게",1);
}
}
Adapter 에 연결하여 추가하는 간단한 예제 입니다.
실제 처리는 CustomAdapter.java 파일에서는 모두 처리하게 됩니다.
다음은 CustomAdapter 에서 처리하는 로직을 보겠습니다.
4. CustomAdapter.java 만듭니다.
public class CustomAdapter extends BaseAdapter {
public class ListContents{
String msg;
int type;
ListContents(String _msg,int _type)
{
this.msg = _msg;
this.type = _type;
}
}
private ArrayList m_List;
public CustomAdapter() {
m_List = new ArrayList();
}
// 외부에서 아이템 추가 요청 시 사용
public void add(String _msg,int _type) {
m_List.add(new ListContents(_msg,_type));
}
// 외부에서 아이템 삭제 요청 시 사용
public void remove(int _position) {
m_List.remove(_position);
}
@Override
public int getCount() {
return m_List.size();
}
@Override
public Object getItem(int position) {
return m_List.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final int pos = position;
final Context context = parent.getContext();
TextView text = null;
CustomHolder holder = null;
LinearLayout layout = null;
View viewRight = null;
View viewLeft = null;
// 리스트가 길어지면서 현재 화면에 보이지 않는 아이템은 converView가 null인 상태로 들어 옴
if ( convertView == null ) {
// view가 null일 경우 커스텀 레이아웃을 얻어 옴
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.activity_chatitem, parent, false);
layout = (LinearLayout) convertView.findViewById(R.id.layout);
text = (TextView) convertView.findViewById(R.id.text);
viewRight = (View) convertView.findViewById(R.id.imageViewright);
viewLeft = (View) convertView.findViewById(R.id.imageViewleft);
// 홀더 생성 및 Tag로 등록
holder = new CustomHolder();
holder.m_TextView = text;
holder.layout = layout;
holder.viewRight = viewRight;
holder.viewLeft = viewLeft;
convertView.setTag(holder);
}
else {
holder = (CustomHolder) convertView.getTag();
text = holder.m_TextView;
layout = holder.layout;
viewRight = holder.viewRight;
viewLeft = holder.viewLeft;
}
// Text 등록
text.setText(m_List.get(position).msg);
if( m_List.get(position).type == 0 ) {
text.setBackgroundResource(R.drawable.inbox2);
layout.setGravity(Gravity.LEFT);
viewRight.setVisibility(View.GONE);
viewLeft.setVisibility(View.GONE);
}else if(m_List.get(position).type == 1){
text.setBackgroundResource(R.drawable.outbox2);
layout.setGravity(Gravity.RIGHT);
viewRight.setVisibility(View.GONE);
viewLeft.setVisibility(View.GONE);
}else if(m_List.get(position).type == 2){
text.setBackgroundResource(R.drawable.datebg);
layout.setGravity(Gravity.CENTER);
viewRight.setVisibility(View.VISIBLE);
viewLeft.setVisibility(View.VISIBLE);
}
// 리스트 아이템을 터치 했을 때 이벤트 발생
convertView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 터치 시 해당 아이템 이름 출력
Toast.makeText(context, "리스트 클릭 : "+m_List.get(pos), Toast.LENGTH_SHORT).show();
}
});
// 리스트 아이템을 길게 터치 했을때 이벤트 발생
convertView.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// 터치 시 해당 아이템 이름 출력
Toast.makeText(context, "리스트 롱 클릭 : "+m_List.get(pos), Toast.LENGTH_SHORT).show();
return true;
}
});
return convertView;
}
private class CustomHolder {
TextView m_TextView;
LinearLayout layout;
View viewRight;
View viewLeft;
}
}
ViewHolder 에 대한 소스가 포함되어 있습니다.
ViewHolder 는 getView의 속도 향상을 위해 사용됩니다.
한번의 findViewByID 로 재사용 하기 위해 viewHolder를 사용 합니다.
샘플소스 입니다.
chatui.zip