普通图片会被均匀拉伸,如下:
会被均匀拉伸成
使用效果非常差,可以使用9-patch图片来进行改善。、
在Android Studio中,我们可以将任何png类型的图片制作成9-Patch图片。
步骤如下:
首先对着 message_left.png 图片右击 → Create 9-Patch file,会出现如下图片:
在上边框和左边框绘制的部分表示当图片需要拉伸时就拉伸黑点标记的区域
在下边框和右边框绘制的部分表示内容允许被放置的区域
需要删掉原来的图片,因为Android项目中不允许同一文件夹下有两张相同名称的图片!!!!
设计聊天界面:
新建两个子布局 msg_left_item.xml 和 msg_right_item.xml
msg_left_item代码如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:background="@drawable/message_left" >
<TextView
android:id="@+id/leftMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="#fff" />
</LinearLayout>
</FrameLayout>
msg_right_item代码如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:background="@drawable/message_right">
<TextView
android:id="@+id/rightMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="#000" />
</LinearLayout>
</FrameLayout>
分别用两个设计好的9-patch图作为背景。
然后创建RecyclerView的适配器,新建类MsgAdapter,代码如下:
class MsgAdapter(private val msgList: List<Msg>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
inner class LeftViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val leftMsg: TextView = view.findViewById(R.id.leftMsg)
}
inner class RightViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val rightMsg: TextView = view.findViewById(R.id.rightMsg)
}
override fun getItemViewType(position: Int): Int {
val msg = msgList[position]
return msg.type
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
if (viewType == Msg.TYPE_RECEIVED) {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.msg_left_item, parent, false)
LeftViewHolder(view)
} else {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.msg_right_item, parent, false)
RightViewHolder(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val msg = msgList[position]
when (holder) {
is LeftViewHolder -> holder.leftMsg.text = msg.content
is RightViewHolder -> holder.rightMsg.text = msg.content
else -> throw IllegalArgumentException()
}
}
override fun getItemCount(): Int = msgList.size
}
根据不同的viewType创建不同的界面。
定义两个viewHolder,LeftViewHolder和RightViewHolder,分别缓存msg_left_item.xml和msg_right_item.xml布局中的控件。然后重写getItemViewType()方法,并在这个方法中返回当前position对应的消息类型。
然后重写三个函数,均按照不同的viewHolder类型来进行创建。
在onCreateViewHolder()方法中根据不同的viewType来加载不同的布局并创建不同的ViewHolder。然后在onBindViewHolder()方法中判断ViewHolder的类型:如果是LeftViewHolder,就将内容显示到左边的消息布局;如果是RightViewHolder,就将内容显示到右边的消息布局。
最后在MainActivity中些如下代码:
class MainActivity : AppCompatActivity(), View.OnClickListener {
private val msgList = ArrayList<Msg>()
private var adapter:MsgAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initMsg()
val layoutManager = LinearLayoutManager(this)
val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = layoutManager
adapter = MsgAdapter(msgList)
recyclerView.adapter = adapter
val send: Button = findViewById(send)
send.setOnClickListener(this)
}
override fun onClick(p0: View?) {
if (p0 != null) {
when (p0.id) {
send ->{
val inputText:TextView = findViewById(R.id.inputText)
val recyclerView:RecyclerView = findViewById(R.id.recyclerView)
val content = inputText.text.toString()
if (content.isNotEmpty()) {
val msg = Msg(content, Msg.TYPE_SEND)
msgList.add(msg)
adapter?.notifyItemInserted(msgList.size - 1)
recyclerView.scrollToPosition(msgList.size-1)
inputText.text = ""
}
}
}
}
}
private fun initMsg(){
msgList.add(Msg("Hello guys!", Msg.TYPE_RECEIVED))
msgList.add(Msg("Hello,who are you?", Msg.TYPE_SEND))
msgList.add(Msg("This is mmm,i love you!", Msg.TYPE_RECEIVED))
}
}
主要是定义了主界面send按钮的点击事件,获得EditText中的文本内容,然后通过Send 按钮发送,并当发送的消息不为空时,调用适配器的notifyItemInserted()方法,通知列表有新的消息插入,从而完成显示。
或者可以使用notifyDataSetChanged()方法,它会将RecyclerView中所有可见的元素全部刷新,这样不管是新增、删除、还是修改元素,界面上都会显示最新的数据,但缺点是效率会相对差一些。
接着调用RecyclerView的scrollToPosition()方法,定位到最后一行,完成显示。