美文网首页Android OtherAndroid开发经验谈Android开发
说说如何使用 Android UI 设计聊天界面

说说如何使用 Android UI 设计聊天界面

作者: deniro | 来源:发表于2018-02-21 17:13 被阅读614次

    1 制作 Nine-Patch 图片

    Nine-Patch 图片是一种被特殊处理的 png 图片,它能够指定哪些区域可以被拉伸而哪些区域不可以。

    先准备一张气泡样式的图片 message_left.png:

    气泡样式图片

    我们把这张图片设置为 LinearLayout 的背景图片:

    <?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="400dp"
        android:background="@drawable/message_left_small"
        >
    
    </LinearLayout>
    
    
    气泡被拉伸变形

    这样的展示效果,用户体验很差。

    因此,我们需要制作 9-patch 的 png 图片。

    在 Android Studio 中,右键选中要制作 9-patch 的 png 图片,在弹出的列表中选择 “Create 9-Patch file”:


    右键选中制作 9-patch 文件

    在接下来的弹出框中,指定 9-patch 的 png 图片路径,注意要放在 drawable-xx 等类似的路径下,生成的图片名为 *.9.png:


    指定图片路径与图片名

    创建成功后,双击 *.9.png 文件,打开 9-patch 编辑器:

    9-patch 编辑器

    通过拖拽,设置伸缩的不可变区域,即下图中圈出的黑色区段:


    image.png

    最后删除非 .9 的 png 图片,重新运行程序:

    使用 9-patch 图片

    现在效果好多了吧O(∩_∩)O~

    2 编写聊天界面

    因为是聊天界面,因此会有接收与发送的消息框。我们还要按照上述的方法,再制作一张右侧消息框的 .9 png 图片:

    右侧消息框的 .9 png

    在 app/build.gradle 中加入 RecyclerView 的依赖库:

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
            exclude group: 'com.android.support', module: 'support-annotations'
        })
        compile 'com.android.support:appcompat-v7:24.2.1'
        compile 'com.android.support:recyclerview-v7:24.2.1'
        testCompile 'junit:junit:4.12'
    }
    

    编写主界面:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#d8e0e8"
        >
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/msg"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"/>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <EditText
                android:id="@+id/input"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:hint="请输入"
                android:maxLines="2"
                />
    
            <Button
                android:id="@+id/send"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="发送"
                />
    
        </LinearLayout>
    
    </LinearLayout>
    
    

    在主界面中,我们放置了一个 RecyclerView 作为显示聊天消息的控件,下面嵌套了一个 LinearLayout,里面包含一个 EditText 用于输入消息,一个 Button 用于发送消息的按钮。

    然后定义一个消息实体类:

    public class Msg {
        /**
         * 内容
         */
        private String content;
    
        /**
         * 类型
         */
        private TYPE type;
    
        public enum TYPE{
            /**
             * 接收
             */
            RECEIVED,
            /**
             * 发送
             */
            SENT
        }
    
    
        public Msg(String content,TYPE type){
            this.content = content;
            this.type = type;
        }
    
        public TYPE getType() {
            return type;
        }
    
        public String getContent() {
            return content;
        }
    }
    

    接下来编写 RecyclerView 子项的布局(msg_item.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="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">
    
        <LinearLayout
            android:id="@+id/left_layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left"
            android:background="@drawable/message_left_small">
    
            <TextView
                android:id="@+id/left_msg"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_margin="10dp"
                android:textColor="#fff" />
        </LinearLayout>
    
        <LinearLayout
            android:id="@+id/right_layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:background="@drawable/message_right_small">
    
            <TextView
                android:id="@+id/right_msg"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_margin="10dp"
                />
        </LinearLayout>
    
    
    </LinearLayout>
    

    我们让收到的消息居左对齐,发送的消息居右对齐,并分别使用刚才制作两张 9-patch png 作为背景图。

    下面创建 RecyclerView 的适配器类:

    public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {
    
        private List<Msg> msgList;
    
        static class ViewHolder extends RecyclerView.ViewHolder {
    
            LinearLayout leftLayout;
            LinearLayout rightLayout;
    
            TextView leftMsg;
            TextView rightMsg;
    
            public ViewHolder(View itemView) {
                super(itemView);
                leftLayout=(LinearLayout) itemView.findViewById(R.id.left_layout);
                rightLayout=(LinearLayout)itemView.findViewById(R.id.right_layout);
                leftMsg=(TextView) itemView.findViewById(R.id.left_msg);
                rightMsg=(TextView) itemView.findViewById(R.id.right_msg);
            }
        }
    
        public MsgAdapter(List<Msg> msgList) {
            this.msgList = msgList;
        }
    
        @Override
        public MsgAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
           View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);
            return new ViewHolder(view);
        }
    
        @Override
        public void onBindViewHolder(MsgAdapter.ViewHolder holder, int position) {
            Msg msg=msgList.get(position);
            switch (msg.getType()){
                case RECEIVED://接收的消息
                    holder.leftLayout.setVisibility(View.VISIBLE);
                    holder.rightLayout.setVisibility(View.GONE);
                    holder.leftMsg.setText(msg.getContent());
                    break;
                case SENT://发出的消息
                    holder.leftLayout.setVisibility(View.GONE);
                    holder.rightLayout.setVisibility(View.VISIBLE);
                    holder.rightMsg.setText(msg.getContent());
                    break;
            }
        }
    
        @Override
        public int getItemCount() {
            return msgList.size();
        }
    }
    

    这里根据消息的类型,来决定每一个子项显示哪一种样式。

    最后修改活动类的代码,为它初始化数据,并为发送按钮加入响应事件:

    public class MainActivity extends AppCompatActivity {
    
        private List<Msg> msgList = new ArrayList<>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            init();
    
            final EditText inputText=(EditText)findViewById(R.id.input);
            Button sendBtn=(Button)findViewById(R.id.send);
    
            final RecyclerView msgRecyclerView=(RecyclerView)findViewById(R.id.msg);
            LinearLayoutManager layoutManager=new LinearLayoutManager(this);
            msgRecyclerView.setLayoutManager(layoutManager);
    
            final MsgAdapter adapter=new MsgAdapter(msgList);
            msgRecyclerView.setAdapter(adapter);
    
            sendBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String content=inputText.getText().toString();
                    if("".equals(content))
                        return;
    
                    msgList.add(new Msg(content, Msg.TYPE.SENT));
    
                    //如果有新消息,则设置适配器的长度(通知适配器,有新的数据被插入),并让 RecyclerView 定位到最后一行
                    int newSize = msgList.size() - 1;
                    adapter.notifyItemInserted(newSize);
                    msgRecyclerView.scrollToPosition(newSize);
    
                    //清空输入框中的内容
                    inputText.setText("");
    
    
                }
            });
    
        }
    
        /**
         * 初始化消息数据
         */
        private void init() {
            msgList.add(new Msg("你好", Msg.TYPE.RECEIVED));
            msgList.add(new Msg("你好,请问你是?", Msg.TYPE.SENT));
            msgList.add(new Msg("我是 deniro,很高兴认识你^_^", Msg.TYPE.RECEIVED));
        }
    }
    

    运行程序:

    聊天界面效果

    相关文章

      网友评论

      • 简书取名好难:2个字你好气泡图这么大 是.9图吗
        deniro:@简书取名好难 缩放的区域是在编辑器中自定义的
        简书取名好难:@简书取名好难 .9图不都是根据 内容的多少来缩放吗?比如说QQ 微信 你好跟非常好 它们的气泡就不一样大
        deniro:@简书取名好难 你好,是的

      本文标题:说说如何使用 Android UI 设计聊天界面

      本文链接:https://www.haomeiwen.com/subject/okjgtftx.html