第一部分:9.png图像的制作

遥想当年Android2.3的时代,手机不Root那基本没得玩,我那个时候荒废了不少时间搞什么系统美化,反编译啊什么的。虽然到头来竹篮打水,但是也算对计算机有了一定的兴趣。当时我最害怕就是9.png图像,因为只要涉及到修改这个的操作,那我是回编译不成功的。现在的我好好的瞥了两眼9.png的制作方法,这有什么难的?

首先《第一行代码中》的方法过时了,这项功能已经被集成到AS当中了,我们把图片放在文件夹里面后,点击图片右键选择create 9-Patch file

随后点击确认,在新生成的文件上操作就行了。具体的注意事项以及重点参见.9.png中四条黑线的意义。【注意:制作完成后,应该将原始文件删除,否则AS会分不清楚而报错。】

第二部分:制作聊天界面

  • 开始之前先把RecyclerView引过来。打开app中的build.gradle,在其中的dependencies中加上
    implementation 'com.android.support:recyclerview-v7:28.0.0'

这个与书上的不同,因为过时了。版本号与com.android.support:appcompat-v7:28.0.0相同即可。

随后同步build.gradle

  • 因为打开就显示界面,所以肯定是在主布局里面写。我们需要一个线性布局,布局应该是垂直的。上面是RecyclerCiew,底部有两个控件,左边是EditView右边是Button,但是因为主布局是垂直的,所以我们在布局中再加入一个水平的布局,底下的两个控件都在水平布局里面。

    <?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.RecyclerViewandroid:id="@+id/msg_recycle_view"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" /><!--下面的布局是水平方向的,不写出来默认就是水平--><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content" ><EditTextandroid:id="@+id/input_text"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:hint="Type something here"android:maxLines="2" /><Buttonandroid:id="@+id/send"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Send" /></LinearLayout></LinearLayout>
    

    这里复习一下layout_weight的用法,我印象中这个只有在LinearLayout中才可以使用,使用之后,系统会把所有组件的weight相加,然后把空间按需分配。但是与match_parent不同的是,系统会给其他控件保留最小的尊严。比如上面的的栗子,RecyclerView的weight为1,但它下面还有输入框和按钮,所以系统为下面两个控件留了位置。又比如下面输入框的weight也是1,系统在水平方向上为button保留了位置。【水平状态下,weight抵消width;垂直状态下,weight抵消height】

  • 因为我们使用了RecyclerView,所以我们需要为其编写子项布局。新建一个布局文件,我们意识到这个布局文件里面只会出现TextView,但是发出和接受消息的方向是不同的,比如发出的都会在右面出现,接受的都会在左面出现。所以我们要声明两个TextView。接下来就有意思了,书上面给出的栗子是每个TextView的外层嵌套了一个LinearLayout,而如果你直接写出来两个TextView在一个线性布局里面也是可以通过的,这是两者的区别。

对比图

可以看得出来,没有嵌套的 字几乎是贴着图片的,而嵌套着的显得更加的自然。这就是与郭神的差距啊。

<?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="wrap_content"android:padding="10dp" ><LinearLayoutandroid:id="@+id/left_layout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="left"android:background="@drawable/message_left" ><TextViewandroid: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><LinearLayoutandroid:id="@+id/right-layout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="right"android:background="@drawable/message_right" ><TextViewandroid:id="@+id/right_msg"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_margin="10dp" /></LinearLayout></LinearLayout>

这里说一下layout_margin的含义,它在线性布局里的意思是view距离父view的距离。正因为如此,TextView才可以与嵌套着的LinearLayout形成缝隙,这是不嵌套没法做出来的。

  • 第三部分:RecyclerView适配器和信息类

信息类Msg,我们的消息分为接收的消息和发送的消息,他们唯一的区别就是在屏幕上的位置不同,因此我们需要定义消息的状态,int就可以。有了信息的状态,当然还需要信息的内容啊,接下来定义几个接收器就可以了。

package com.example.uibestpractice;public class Msg {//普通的记录消息的类public static final int TYPE_RECEIVED=0;public static final int TYPE_SEND=1;private String content;private int Type;public Msg(String content,int Type){this.content=content;this.Type=Type;}public String getContent(){return content;}public int getType(){return Type;}}
  • 制作RecyclerView的适配器

开始制作适配器,都是一样的套路,首先声明一个类MsgAdapter继承RecyclerView.Adapter<MsgAdapter.ViewHolder>,其中ViewHolder是我们定义在类中的一个静态类,继承自RecyclerView.ViewHolder,在这个静态类中我们需要实例化我们RecyclerView布局中的控件,有两个LinearLayout和两个TextView,都在构造函数中进行,但是构造函数必须满足父类的构造函数,因此传一个view进去就可以了。

我们的主类的构造函数很简单,只需要接收一个List即可,将接受的List传给字段。这个List里面存储的都是Msg类的对象。

随后重写 onCreateViewHolder,onBindViewHolder以及getItemCount三种方法。先来说最简单的getItemCount,只需要返回list的size即可。

接着看onCreateVIewHolder,这个方法是动态RecyclerView实例的,所以声明

View view =LayoutInflater.from(paremt.context).inflate(子项id,parent,false);
retuen new ViewHolder(view);

再来onBindViewHolder,这个是要赋给内部类字段属性,首先先建立对应position的Msg的对象,如果这个对象的是接受的消息,那么我们就把对应发送消息的LinearLayout,view.GONE掉。,显示出来接受消息的LinearLayout。注意一定是GONE,不是INVISIBLE,否则后果如下:

上正确的代码

package com.example.uibestpractice;import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;import java.util.List;public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {private List<Msg> mMsgList;static class ViewHolder extends RecyclerView.ViewHolder{LinearLayout leftLayout;LinearLayout rightLayout;TextView leftMsg;TextView rightMsg;public ViewHolder(View view){super(view);leftLayout=(LinearLayout) view.findViewById(R.id.left_layout);//因为layout是在文件中,所以是R.idrightLayout=(LinearLayout) view.findViewById(R.id.right_layout);leftMsg=(TextView) view.findViewById(R.id.left_msg);rightMsg=(TextView) view.findViewById(R.id.right_msg);}}public MsgAdapter(List<Msg> mMsgList){this.mMsgList=mMsgList;}@Overridepublic ViewHolder onCreateViewHolder( ViewGroup parent, int i) {
//这里的i是viewtype,在这个项目中没有用到。主要解决一个RecyclerView加载不同子项item问题。View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);return new ViewHolder(view);}@Overridepublic void onBindViewHolder(ViewHolder holder, int position) {Msg msg=mMsgList.get(position);if(msg.getType()== Msg.TYPE_RECEIVED){holder.leftLayout.setVisibility(View.VISIBLE);holder.rightLayout.setVisibility(View.GONE);holder.leftMsg.setText(msg.getContent());}else if (msg.getType()==Msg.TYPE_SEND){holder.rightLayout.setVisibility(View.VISIBLE);holder.leftLayout.setVisibility(View.GONE);holder.rightMsg.setText(msg.getContent());}}@Overridepublic int getItemCount() {return mMsgList.size();}
}
  • 最后就是在主类中实例化了​​​​

首先实例化RecyclerView;因为我们要点击button,所以也有它的份;实例化button为了获得EditView的内容啊,所以这个编辑框也得实例化;实例化适配器;最后规定RecyclerView的格式,这次依然是传统格式。

我们还需要为button建立一个监听器,我们需要将编辑框的内容发送到RecyclerView上

①获取内容,将字符串添加到List当中去。

②调用适配器的notifyItemInserted方法,通知有新的数据加入了,赶紧将这个数据加到RecyclerView上面去。

③调用RecyclerView的scrollToPosition方法,以保证一定可以看的到最后发出的一条消息。

最后我没有按照书上的栗子初始化List,修改了一下,现在你可以自己和自己聊天了。

package com.example.uibestpractice;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private List<Msg> msgList=new ArrayList<>();private EditText editText;private Button button;private RecyclerView recyclerView;private  MsgAdapter adapter;private boolean Send=true;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);editText=(EditText) findViewById(R.id.input_text);button=(Button) findViewById(R.id.send);recyclerView=(RecyclerView) findViewById(R.id.msg_recycle_view);adapter=new MsgAdapter(msgList);LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);recyclerView.setLayoutManager(linearLayoutManager);recyclerView.setAdapter(adapter);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String content=editText.getText().toString();if (!"".equals(content)){Msg msg;if (Send){ msg=new Msg(content,Msg.TYPE_SEND);}else{ msg=new Msg(content,Msg.TYPE_RECEIVED);}Send=!Send;msgList.add(msg);adapter.notifyItemInserted(msgList.size()-1);recyclerView.scrollToPosition(msgList.size()-1);editText.setText("");}}});
}

希望所有认真的同学都能有一个好的结果,祝你晚安。

                                                                                                                                  ------2018.10.3于图书馆

《第一行代码》 编写精美的聊天界面相关推荐

  1. 编写精美的聊天界面(左边显示接收消息,右边显示发送消息)(项目已上传GitHub)

    附上我的GitHub项目地址: https://github.com/Skymqq/UIChat.git 学习Android开发,了解一个精美聊天界面的实现是很有必要的,如果可以掌握这个技能,那么在下 ...

  2. 第一行代码:知晓当前是哪个界面

    public class BaseActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceSta ...

  3. 第一行代码学习笔记第三章——UI开发的点点滴滴

    知识点目录 3.1 如何编写程序界面 3.2 常用控件的使用方法 * 3.2.1 TextView * 3.2.2 Button * 3.2.3 EditText * 3.2.4 ImageView ...

  4. 《第一行代码》第三版笔记

    文章目录 第一章 1.3.5 详解项目中的资源 1.3.6 详解build.gradle文件 第二章 2.1 kotlin语言简介 2.2 如何运行kotlin代码 2.7.2 判空辅助工具 第三章 ...

  5. 第一行代码 Android (郭霖 著)

    https://github.com/guolindev/booksource 第1章 开始启程----你的第一行Android代码 (已看) 第2章 先从看得到的入手----探究活动 (已看) 第3 ...

  6. Java学习经典《第一行代码》第二版

    第1章 开始启程--你的第一行Android代码 1 1.1 了解全貌--Android王国简介 2 1.1.1 Android系统架构 2 1.1.2 Android已发布的版本 3 1.1.3 A ...

  7. 第一行代码——Android pdf

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 下载地址 ...

  8. 怎么编写提醒人结账的短信息_我如何在短短8个月的时间里从编写第一行代码到获得$ 226K的工作机会...

    怎么编写提醒人结账的短信息 I got offers from Google, Lyft, Yelp, cloud unicorn Rubrik, IBM Artificial Intelligenc ...

  9. html中第一行代码,HTML5 CSS3初学者指南(1) – 编写第一行代码

    介绍 网络时代已经到来.现在对人们来说,每天上网冲浪已经成为一种最为常见的行为. 在网页浏览器中输入一段文本地址,就像http://www.codeproject.com,等待一下,网页就加载到浏览器 ...

最新文章

  1. leetcode 24: 两两交换链表中的节点
  2. spring(四):spring与mybatis结合
  3. 图像处理之基础---特征向量的 几何意义
  4. hdu 1255 覆盖的面积 (Bruceforce)
  5. php 判断是否ipv6,PHP IPV6正则表达式验证代码
  6. 【转】显卡:ATI和NVIDIA两大主流显卡比较
  7. linux下的inode相关知识
  8. 阶段1 语言基础+高级_1-3-Java语言高级_09-基础加强_第1节 基础加强_1_今日内容(1)...
  9. 小米笔记本 镜像_小米笔记本Air 13.3原装WIN10出厂系统ISO镜像1607原版镜像下载
  10. 最新emoji表情代码大全_2020最新版早上好问候图片大全 表情
  11. 连读、变音、失音、浊化、弱读、节奏
  12. SpringBoot笔记(五)Linux系统与项目部署
  13. wnmp mysql 密码_WNMP完整教程
  14. 联想RS550服务器安装Ubuntu16.04
  15. 数组----二维数组
  16. 荣耀智慧屏和荣耀智慧屏PRO的配置
  17. 拼多多店铺怎么布置装修,订单才能暴涨?
  18. WINCE 实用技巧 之 创建快捷方式详解
  19. STM32HAL库RTC闹钟事件
  20. 今日头条-快速获取爆文素材的5大途经

热门文章

  1. 高清(200万像素)多灯红外防水枪型网络摄像机 DH-IPC-HFW5200-IRA
  2. linux网易云命令行,网易云音乐还有命令行版本?倒适合部署在Linux系统的机器人上...
  3. 老男孩linux运维实战培训中心讲师介绍
  4. 斯伦贝谢好进吗_抽血时会抽到肉吗?网友:想想就疼
  5. pd.get_dummies用法
  6. 第三章 虚拟仪器系统I/O接口软件——VISA
  7. 浅析供应链采购管理的痛点
  8. python爬取淘宝搜索页面+url+图片下载并将信息保存到MySQL数据库中
  9. html+css实战187-banner图
  10. 多种方法解决rem字体适配