简单的仿QQ聊天界面与绘制.9图
1.气泡的准备:为了避免图片的失真需要用到如下工具:
在Android sdk 目录下有一个tools 文件夹,在这个文件夹中找到draw9patch.bat 文件,
我们就是使用它来制作Nine-Patch 图片的。双击打开之后,在导航栏点击File→Open 9-patch
将图片加载进来
我们可以在图片的四个边框绘制一个个的小黑点,在上边框和左边框绘制的部分就表示
当图片需要拉伸时就拉伸黑点标记的区域,在下边框和右边框绘制的部分则表示内容会被放
置的区域。
最后点击导航栏 File→Save 9-patch 把绘制好的图片进行保存,此时的文件名就是.9.png。
2.布局文件如下 activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.simple.MainActivity" > <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#ffffff" android:dividerHeight="5dp" android:scrollbars="none" android:divider="#ffffff"/> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal"> <EditText android:id="@+id/editText" android:layout_width="0dp" android:layout_weight="1" android:hint="请输入..." android:layout_height="match_parent"/> <Button android:id="@+id/btn_send" android:layout_marginLeft="5dp" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="发送"/> </LinearLayout> </LinearLayout>
msg_item.xml:消息的布局,ListView的子条目如下:
<!-- 将左右两边的消息放在一个布局,通过信息的类型而隐藏掉相对的布局 android:gravity="center|left" 让文字居中且过长的时候换行靠左显示 --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.simple.MainActivity" > <LinearLayout android:id="@+id/left_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <ImageView android:id="@+id/ivicon" android:layout_width="30dp" android:layout_height="30dp" android:layout_gravity="top" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/left_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_marginRight="100dp" android:layout_marginTop="8dp" android:background="@drawable/left" android:gravity="center|left" android:padding="8dp" android:text="左边默认的文字" /> </LinearLayout> <LinearLayout android:id="@+id/right_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="right" android:orientation="horizontal" > <TextView android:id="@+id/right_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="100dp" android:layout_marginRight="5dp" android:layout_marginTop="8dp" android:layout_weight="1" android:background="@drawable/right" android:gravity="center|left" android:padding="8dp" android:text="右边默认的文字" /> <ImageView android:id="@+id/right_image" android:layout_width="30dp" android:layout_height="30dp" android:src="@drawable/app_lvjian_message_background" /> </LinearLayout> </LinearLayout>
注意:这里右边的消息如果不设置权重让右边的图片先显示,如果内容过长会把图片挤出外面
3.消息的实体类:Message.java
/**消息的实体类:包括content消息内容 type消息类型 */ public class Message { private String content;//内容 private boolean type;//消息类型,该消息是否是自己发送 public Message() { super(); } /** * @param content 消息内容 * @param type 消息类型:true代表是自己发送 false代表是接收到的消息 */ public Message(String content, boolean type) { super(); this.content = content; this.type = type; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public boolean isType() { return type; } public void setType(boolean type) { this.type = type; } }
4.适配器 MyAdapter.java:
//自定义的Adapter加载布局文件的时候需要判断是哪方发送的消息来决定用哪个item布局文件 public class MyAdapter extends BaseAdapter { private List<Message> list;// Message包括消息类型和消息 private Context context; public MyAdapter(Context context, List<Message> list) { super(); this.list = list; this.context = context; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; View view = null;//装所有消息的布局 if (convertView == null) { holder = new ViewHolder(); view = LayoutInflater.from(context).inflate(R.layout.msg_item, null); holder.leftMsg = (TextView) view.findViewById(R.id.left_text); holder.leftLayout = (LinearLayout) view.findViewById(R.id.left_layout); holder.rightLayout = (LinearLayout) view.findViewById(R.id.right_layout); holder.rightMsg = (TextView) view.findViewById(R.id.right_text); view.setTag(holder); } else { view=convertView;//将翻出去的视图对象赋值给view,对象的重复使用 holder = (ViewHolder) view.getTag(); } Message msg=list.get(position);//获取消息的对象 if(msg.isType()){//如果是自己发送的 holder.rightMsg.setText(msg.getContent());//将信息内容设置到TextView中显示 holder.leftLayout.setVisibility(View.GONE);//设置左边的布局不可见且不占用位置 holder.rightLayout.setVisibility(View.VISIBLE);//设置右边的布局可见 }else{//如果是收到的消息 holder.leftMsg.setText(msg.getContent()); holder.leftLayout.setVisibility(View.VISIBLE); holder.rightLayout.setVisibility(View.GONE); } return view; } // 提高效率 class ViewHolder { LinearLayout leftLayout; LinearLayout rightLayout; TextView leftMsg; TextView rightMsg; } }
5.MainActivity.java
public class MainActivity extends Activity { private EditText editText;//编辑信息的编辑框 private Button btn_send;//发送消息的按钮 private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (EditText) findViewById(R.id.editText); btn_send = (Button) findViewById(R.id.btn_send); listView = (ListView) findViewById(R.id.listView); //模拟几条消息 final List<Message> list=new ArrayList<Message>(); list.add(new Message("在吗?", false));//false代表是接收到的消息 list.add(new Message("草你妈,不回我",false)); list.add(new Message("就是不回,你能拿我怎么滴!!!",true)); list.add(new Message("咖啡骄傲的算法来房间了发打发斯蒂芬打发大师傅阿道夫阿道夫",false)); final MyAdapter adapter=new MyAdapter(this, list); listView.setAdapter(adapter); btn_send.setOnClickListener(new View.OnClickListener() { @Override//发送信息按钮监听 public void onClick(View v) { String str=editText.getText().toString();//编辑框的内容 if(!TextUtils.isEmpty(str)){ list.add(new Message(str, true)); adapter.notifyDataSetChanged(); //刷新ListView listView.setSelection(list.size()); // 将ListView定位到最后一行 editText.setText("");//清空输入框 } } }); } }
效果图如下: