关于UI设计的部分总结
此部分重点关注RecyclerView部分的设计工作
首先在调用没有直接导入的库或者插件的时候,需要在build.添加相应模块
之后,布局主布局。,或者父布局
这回的UI示例如下:

布局代码如下:
<?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_recycler_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> </android.support.v7.widget.RecyclerView> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/input_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:hint="something here" android:maxLines="2" /> <Button android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send"/> </LinearLayout> </LinearLayout>
我们分层对这部分的代码进行分析:首先是对整体布局进行查看:
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#d8e0e8"
我们将布局设置为垂直布局,并将颜色设定为特定的颜色,将布局的宽度设定为铺满整个父布局(对于此来讲就是整个屏幕)
之后是最上层的RecyclerView插件:
<android.support.v7.widget.RecyclerView
android:id="@+id/msg_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</android.support.v7.widget.RecyclerView>
我们将这个插件的权重设定为1,这样当其他插件没有设定权重的情况下,如果设定的长宽为根据内容进行设定,则会处于最底层(因为我们设定的排列方式为按照垂直的方式进行排列
)。EditText和Button没有过多的附加选项,这里不做过多的解释。主插件布局完毕后,效果图如下:

RecyclerView里面是不能进行详细设定的,即使可以管理起来也不方便。为此,我们需要对这种可以包含一个子布局的组件建立一个额外的布局文件,用于存储详细的子布局信息。布局效果如下:
<?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"> <!--左边为显示收到的信息--> <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"> <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"> <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>
子布局分为左右两个子布局,最上面的Padding为两个子布局与外层边框的距离,每个布局都有一个对应的图片作为背景图,方便识别到底代表发送还是接受的部分。
每一个List组件都需要一个Adapter作为设定相关List信息的必要组件,此处的Adapter代码如下:
package com.example.lordage.uipractice; 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; /** * Created by lordage on 2017/7/25. */ 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){ //所谓ViewHolder,即是将一个布局进行打包,然后统一调用 //所谓ViewHolder,即将大部分的代码分放到一个ViewHolder中,调用的时候一齐调用,但是对这一组组件进行统一处理操作 super(view); leftLayout = (LinearLayout) view.findViewById(R.id.left_layout); rightLayout = (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> msgList){ mMsgList = msgList; } @Override public 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(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_SENT){ holder.rightLayout.setVisibility(View.VISIBLE); holder.leftLayout.setVisibility(View.GONE); holder.rightMsg.setText(msg.getContent()); } } @Override public int getItemCount(){ return mMsgList.size(); } }
首先第一行:
private List<Msg> mMsgList;
用于设定列表所要做为对应List的相关列表选项(即将RecyclerView作为可视的mMsgList)
之后是ViewHolder。此处的ViewHolder代表List中每一个Item对应的布局中组件的管理。此处对应的就是左右布局,以及左右布局中的TextView部分
ViewHolder之后是MsgAdapter的构造函数,只要将对应的msgList导入即可
之后是创建ViewHolder。LayoutInflater这个类的作用即是在一个布局中调用另外一个布局,其中的第三个boolean参数是判断是否要在这个套进去的子布局中加上父布局,我们这里选择的是false,否则没法添加到list里的item中。而我们的布局文件自然是之前的msg_item,即左右布局这个文件
在之后就是 onBindViewHolder方法。此方法为在获取相应位置的时候调用的方法。当在一个特定位置的时候,根据位置获取列表中对应的msg信息
Msg msg = mMsgList.get(position);
之后再根据其属于的内容,设定这个list的item中各个组件的是否可见以及可见的相关内容
这样我们的list就算是完成初始布局。此时需要在主活动中调用这些组件了。主活动代码如下:
package com.example.lordage.uipractice; 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.ListView; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private List<Msg> msgList = new ArrayList<>(); private EditText inputText; private Button sendButton; private RecyclerView msgRecyclerView; private MsgAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initMsgs(); inputText = (EditText) findViewById(R.id.input_text); sendButton = (Button) findViewById(R.id.send); msgRecyclerView = (RecyclerView) findViewById(R.id.msg_recycler_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); msgRecyclerView.setLayoutManager(layoutManager); adapter = new MsgAdapter(msgList); msgRecyclerView.setAdapter(adapter); sendButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String content = inputText.getText().toString(); if (!"".equals(content)){ Msg msg = new Msg(content, Msg.TYPE_SENT); msgList.add(msg); adapter.notifyItemInserted(msgList.size()-1); msgRecyclerView.scrollToPosition(msgList.size() - 1); inputText.setText(""); } } }); } private void initMsgs(){ Msg msg1 = new Msg("Hello guy.", Msg.TYPE_RECEIVED); msgList.add(msg1); Msg msg2 = new Msg("Hello. Who is that?", Msg.TYPE_SENT); msgList.add(msg2); Msg msg3 = new Msg("This is Tom. Nice talking to you. ", Msg.TYPE_RECEIVED); msgList.add(msg3); } }
首先是变量。我们需要对输入框、发送按钮进行交互处理,因此需要这两个组件的相关饮用。之后是RecyclerView的引用以及对RecyclerView设置的adapter。由于adapter我们有自己设定,因此此处的adapter为MsgAdapter。信息存储我们通过List<Msg>来处理。
主代码部分
initMsg();
为初始化信息,此处为调用最底下的initMsgs方法。
之后是设定按钮的饮用、RecyclerView的引用,以及List的布局管理器。此处为直接设置为垂直布局,并且调用当前布局中的相关信息。在导入msgList和adapter后,再对发送按钮进行相关的设定。再发送信息后,需要将输入的信息添加到适当的位置。位置即为msgList.size() - 1(初始位置为0),并设定滚动的位置为最后的信息。(你总不希望收到了好多信息可显示的还是以前的信息)。再将输入框中的字符串设置为空字符串,整个操作完成。

浙公网安备 33010602011771号