布局

0、约束布局

1、线性布局(LinearLayout)

常见属性

以下属性为常见属性,除了最后一个。

1、组件名称:+id/

android:+id/name:代表声明一个新的元素
android:id/name:代表直接使用以及存在的元素

2、组件高宽:

android:layout_width
android:layout_height
1、属性值:
wrap_content 代表实际内容尺寸
match_parent 与父级元素尺寸
fill_parent 填充整个父级尺寸2、属性值单位:
尺寸单位:dp

3、组件背景:backgroud

adnroid:backgroud
属性值:颜色代码、图片

4、同级元素或者与父控件距离:layout_margin*

android:layout_margin*

5、子元素之间距离:layout_padding*

android:layout_padding*

6、子元素排列方向:orientation

在父容器中设置android:orientation
属性值:
1、垂直:vertical
2、水行:horizontal
3、默认水平方向,左边排列

7、子元素对齐方式:grivity

在子元素中设置:android:grivity
比如在底部,垂直居中、右上角等,

8、子元素空间占比权重:layout_weight

子元素中设置:layout_weight
1、比如两个元素的高宽均为0dp,权重都为1,表示各种权重为1,各占50%的空间。
2、如果一个元素的宽为50dp,权重各为1,代表1元素先占50dp,剩余均分

9 一行显示:sigleLine

true即为一行显示

2、相对布局(RelativeLayout)

以下属性为常见属性。

1、在某元素左侧

android:layout_toLeftOf

2、在某元素右侧

android:layout_toRightOf

3、跟某元素的底部对齐

android:layout_alignBottom

4、在父元素底部对齐

android:layout_alignParentBottom

5、在谁的下面

android:layout_layout_below

其他控件

1. TextView

1、主要内容如下

1.文字大小
2.超出省略号
3.文字+icon
4.中划线-下划线
5.跑马灯

在布局中声明元素后,通过findViewById(R.id.元素id)

现在实现个按钮点击后,实现如上TextView文字效果。

2.1、第一步:

在布局文件中,声明一个button,id是btn_textView,然后在acitivity中创建点击事件。

//声明button变量
private Button mbtnTextView;
@override
protected void onCreate(Bunle saveInstanceSate){super.onCreate(saveInstanceState);setContentView(R.layout.activity_main);mbtnTextView = (Botton)findViewById(R.id.btn_textView)//单击事件mbtnTextView。setOnClikeListener(new View.OnClikListener){@overridepublic void onClik(View v){//跳转到TextView}};)
}

2.2、第二步:

创建一个新的TextView activity作为独立界面,androidMainFest.xml注册。并继续在button单击事件中添加如下代码:

Intent intent = new Intent(当前activity类名.this,TextViewactivity.class);
startActivity(intent)

2.3、第三步:

修改TextViewTextView.xml布局,增加一个TextView组件。常见属性如下:

android:text 是文本android:textColor 颜色android:textSize 字体大小,单位spandroid:ellipsize="end" 超出尺寸文本用...代替。android:drawableRight="@drawable/icon_xx" 给文本右侧设置一个图片android:drawablePadding 文字与图片距离

3、中划线、下划线需要在代码中设置:

tv = findViewById(R.id.tv4)
tv.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
//去锯齿
tv.getPaint().setAntAlias(true)

4、跑马灯效果:

android:singleLine=true
android:ellipsize=marquee
android:marqueeRepeatLimit="marquee_foever"
android:focusable=true 焦点才能一直有效果
android:focusableIntochModel=true

2. button

1、圆角button

在drawable创建一个drawable resouce file 文件bg_btn,root element选择share

android:shape 图形属性
android:color 填充颜色
<corners android:radius='5dp'/> 圆角然后将button的backgroud设置为"@drawable/bg_btn"

2、描边button

在drawable创建一个drawable resouce file 文件bg_bt2

<stroke android:width="1dp"
android:color="#ffccc"/>

然后将button的backgroud换掉即可.

3、button按压效果

<item android:state_pressed="true"><share><solid android:color="#ff9900"/><corners android:radius="5dp"/></share>
</item><item android:state_pressed="false"><share>正常的效果</share>
</item>

4、按钮点击弹窗

在单击事件里:

Toast.makeText(aitive.this,'文本',Toast.LENGTH_SHORT)

3.EditText

1、常见属性

默认EditText是只有下边框的.如果要自定义,需要自建drawable下建立 drawable resouce file文件.
密码框,其他属性与一般ui相同.

<EditText
android:hint="密码"
android:inputType="textPassword"
android:maxLine=1
android:drawableLeft="图标"
andrlid:drawablePadding="5dp"
/>

如果是数字,只需inputType设置为number.

2、 文本变化监听事件

EditText.andTextChangedListener(new View.OnClikListener){@overridepublic beforeTextChange(){//改变之前}@overridepublic onTextChange(CharSequence s,int start,int before,int count){//改变之后//CharSequence是当前输入的文字//日志打印Log.d("input",s.toString())}@overridepublic afterTextChange(){//改变之后}};)

4.单选:RadioButton

1、常见属性

<RadioGroup><RadioButtonandroid:idandroid:layout_widthandroid:layout_heightandroid:text='男'android:check="true" //默认选中,必须有idandroid:orientation="" //方向android:button="@null" //去掉单选小圆圈android:backgroupd="@drawable/select" //自定义样式/>
</RadioGroup>

2、select:自定义样式

<selector>
<share android:state_checked="true">选中效果
</share>
</item><item android:state_checked="false"><share>正常的效果</share>
</selector>

3、监听事件

m=findViewById(R.id.rg1)
m.setOnclickChangeListener(new RadioGroup.OncheckkedChangeListener(){public void onCheckedChange(RadioGroup group,@IDres int checkedId){//选中的redioRadioButton = group.findViewById(checkedId)Toast.make(本activity.this,"",Tost.Lentgh_short).show();}
});

5.UI自定义样式

<shape>
<solid android:color="背景色"/><!--边框设计-->
<stroke  android:width="边框粗细" android:color="边框颜色"/><!--圆角设计-->
<corners
android:bottomLeftRadius="10sp图形左下角圆角"
android:topLeftRadius="10sp"
android:bottomRightRadius="10sp"
android:topRightRadius=""
/><!--颜色渐变-->
<gradient
android:startColor="开始颜色"
android:endColor="结速颜色"
android:centerColor="过度颜色"
android:angle="渐变方向"
android:type="linear渐变方式"/></shape>

渐变方向:

0:从左向右渐变

90:从下向上渐变

180:从右向左渐变

270:从上向下渐变

6.复选框

7.ImageView

ImageView是图片组件.文件通常存储在drawable开头的目录下.不同分辨率的图片存储在不同以drawable开头的目录下.创建一个临时的drawable-xhdpi,复制图片进去.初始的图片设定有android:src="@drawable/图片名称".宽度及高度使用wrap_content,表明根据实际情况来设定.

代码修改图片:

imageView = (ImageView)findViewById(R.id.image_name)
imageView.setImageRrsource(R.drawable.image_name)

8.ProgressBar

原型的加载进度条.加载万,通过控件的可见属性设置即可.可见属性有三种可选:

android:visibility=visible/invisible/gone

visible是可见,默认值;invisible是不可见,但仍然占据位置;gone是不可见,不占用屏幕空间.可以通过如下方法设定:

a.setVisiblebility(View.VISIBLE\View.INVISIBLE\View.GONE)

9.AlertDialog

                AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity4.this);dialog.setTitle("对话框");dialog.setMessage("要回传的数据:你好");//释放点击对话框外部的屏幕关闭对话框dialog.setCancelable(false);//确认按钮的逻辑dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {Toast.makeText(MainActivity4.this,"确认1",Toast.LENGTH_LONG).show();}});//取消按钮的逻辑dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {Toast.makeText(MainActivity4.this,"取消",Toast.LENGTH_LONG).show();}});//显示对话框dialog.show();//finish()

另外需要注意的是,dialog不是阻塞运行的,dialog.show()后面的代码会继续运行.

11.progressDialog加载对话框

是加载对话框,数据完成后,需要手动dialog.dismiss()关闭,不然会一直存在.

12.自定义控件

UI空间都是继承子View,布局都是继承ViewGroup.

view是一种基本空间,在屏幕上划分一块矩形区域,能响应矩形区域内的各种事件.Viewgrup是一种特殊控件,包含不少view和子ViewGROUP.

创建一个自定义title

  • 自定义UI及配置
    自定义一个通用的top bar.就像苹果的title,包括back和exit按钮.

首先创建一个布局,起名为title. 里面为相对布局,增加两个按钮,一个是back一个是exit.back靠top左,exit靠top 右.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/button_back"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="5dp"android:textSize="20sp"android:layout_alignParentLeft="true"android:text="back" /><Buttonandroid:id="@+id/button_exit"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="5dp"android:layout_alignParentRight="true"android:text="exit"android:textSize="20sp" />
</RelativeLayout>

然后在其他action的布局文件中,增加如下配置:

<include layout="@layout/title"></include>

同时在oncreate()代码中隐藏action自带的top bar:

        ActionBar bar=getSupportActionBar();bar.hide();
  • 给布局增加事件

自此,自定义title组件可以看到效果了.但是back和exit的事件需要在每个action写相同的代码,这样很不好.

我们可以通过继承linearlayout,绑定title ui布局文件.

public class TitleLayout extends LinearLayout {public TitleLayout(Context context, @Nullable AttributeSet attrs) {super(context, attrs);LayoutInflater.from(context).inflate(R.layout.title,this);Button back = findViewById(R.id.button_back);back.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {((Activity) getContext()).finish();}});}
}

在布局中替换上面的

<include layout="@layout/title"></include>

如下:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity4">
<com.example.myapplication.TitleLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

13.ListView控件

1、简单的listview使用

listview出镜率非常高.本节演示一个只支持文本的listview.具体步骤如下:

1、创建一个ListViewActivity,在布局中增加listView
2、准备listView数据,用list保存
3、创建listView适配器,适配器将会在内部为数据创建子布局
4、listView设置适配器

1、创建ListViewActivity

创建一个ListViewActivity,并在对应的activity_list_view布局文件中增加listView组件.activity_list_view.xml布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".LlistViewActivity"><ListView android:id="@+id/list_view"android:layout_width="match_parent"android:layout_height="match_parent"tools:layout_editor_absoluteX="87dp"tools:layout_editor_absoluteY="84dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

通过布局可知,listView组件已经填充了整个布局文件.
下面在action里填充数据.

2、初始化数据

用循环生成了array数据,listview无法直接绑定数据,所以要说用ArrayAdapter适配器先处理数据.ListViewActivity.class:

    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_llist_view);//数组填充数据ArrayList data= new ArrayList();for(int i=0;i<100;i++){data.add(i+"x");}//数据适配器,指定了显示的action,以及listview里面的子布局ArrayAdapter<String> adapter = new ArrayAdapter<String>(LlistViewActivity.this, android.R.layout.simple_list_item_1,data);ListView lv = findViewById(R.id.list_view);lv.setAdapter(adapter);}

说明:

ArrayAdapter初始化参数共三个,第一个是当前action,第二个是子布局,第三个是单位.

listView本身其实也是容器,适配器通过指定的子布局进行组装数据,然后listview通过setAdapter(adapter)直接进行装载.
本文使用的内置布局android.R.layout.simple_list_item_1,就是一个简单TextView组件,适配器会根据数据动态的创建TextView用来显示数据.

2、listView显示图片

listView本身是一个容器,里面是子布局.所以要显示图片,我们需要创建一个布局,这个布局没有根容器,然后把子布局放入listView即可.

为了完成这个目标,我们需要做两件事:

1.自定义子布局
2.自定义实现适配器

1、 自定义listView子布局
子布局为右侧为图片,左侧为文字的list. 先用LinearLayout作为根布局,里面放一个图片组件、文本组件。默认横向排列。list_view_child_layout:

<?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="match_parent"><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/list_view_image"android:layout_width="wrap_content"android:layout_height="wrap_content"></androidx.appcompat.widget.AppCompatImageView><TextViewandroid:id="@+id/list_view_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="10dp"></TextView>
</LinearLayout>

2、 创建list记录类
用来设置list的图片,文本。ResouceBean作为资源bean,存储图片.
ResouceBean.class:

public class ResouceBean {private String name;//图片名称private int imageId;//图片IDpublic ResouceBean(String name, int imageId){this.name=name;this.imageId=imageId;}public String getName(){return name;}public int getImageId(){return imageId;}
}

2、 创建适配器

自定义适配器,将接受的数据与子布局进行组装。具体的步骤如下:

1、适配器继承自ArrayAdapter
2、初始化方法参数接收子布局ID
3、重写getView,进行动态装置数据,getView每次滚均会执行
4、

ImageTextAdapter.class

public class ImageTextAdapter extends ArrayAdapter<ResouceBean> {private int child_layout_id;//子布局public ImageTextAdapter(@NonNull Context context, int child_layout_id, @NonNull List<ResouceBean> objects) {super(context, child_layout_id, objects);this.child_layout_id =child_layout_id;}//该方法滚动到屏幕就会调用执行@NonNull@Overridepublic View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {ResouceBean bean = getItem(position);Log.d("ImageTextAdapter 图片ID:",bean.getImageId()+"");//加载子布局,参数1是子布局id,参数2是根布局,参数3是此子布局自身不设置根布局,不然无法添加到listviewView child_layout = LayoutInflater.from(getContext()).inflate(child_layout_id,parent,false);ImageView iv = child_layout.findViewById(R.id.list_view_image);TextView text = child_layout.findViewById(R.id.list_view_text);iv.setImageResource(bean.getImageId());text.setText(bean.getName());return child_layout;}
}

适配器初始化,会接受子布局的Id.

getView()是滚动到屏幕就会调用执行,所以在里面装配子布局. 首先使用getItem()获取要显示的资源bean,然后使用LayoutInflater获得子布局,并且为里面的组件进行赋值.

其中inflate第三个参数是指不为此布局添加父布局,不然将会导致无法添加到listView中.完成设置后,返回子布局.

3、 绑定listView

在listview的ListViewActivity中绑定数据:

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_llist_view);//数组填充数据List<ResouceBean> data = new ArrayList<ResouceBean>();for(int i=0;i<100;i++){ResouceBean bean = new ResouceBean("测试"+i,R.drawable.test);data.add(bean);}//数据适配器,指定了显示的action,以及listview里面的子布局ImageTextAdapter adapter = new ImageTextAdapter(this,R.layout.list_view_child_layout,data);ListView lv = findViewById(R.id.list_view);lv.setAdapter(adapter);}

到此为止,已完成.

3、提升listview性能,优化适配器

在上面的例子中,listview的适配器的getView()方法,每次滚动都会执行,重写加载布局.当滚动快的时候,性能问题就来了.

在getView()方法中有个convertView参数,是对之前布局进行缓存的,可以重用. 所以每次在增加一个convertView的判断,如果不为空,直接将convertView 赋值给child_layout. 修改代码如下:

ImageTextAdapter.class

public class ImageTextAdapter extends ArrayAdapter<ResouceBean> {private int child_layout_id;//子布局public ImageTextAdapter(@NonNull Context context, int child_layout_id, @NonNull List<ResouceBean> objects) {super(context, child_layout_id, objects);this.child_layout_id =child_layout_id;}//该方法滚动到屏幕就会调用执行@NonNull@Overridepublic View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {ResouceBean bean = getItem(position);Log.d("ImageTextAdapter 图片ID:",bean.getImageId()+"");#优先加载缓存子布局View child_layout;if(convertView==null){child_layout = LayoutInflater.from(getContext()).inflate(child_layout_id,parent,false);}else{view=convertView}ImageView iv = child_layout.findViewById(R.id.list_view_image);TextView text = child_layout.findViewById(R.id.list_view_text);iv.setImageResource(bean.getImageId());text.setText(bean.getName());return child_layout;}
}

虽然子布局进行了优化,但是每次findViewById()都会获取控件实例,我们是不是只用取一次就行了? 其实只要把findViewById()获取的实例存储起来,下次利用就好了.完整的适配器代码如下:

public class ImageTextAdapter extends ArrayAdapter<ResouceBean> {private int child_layout_id;//子布局public ImageTextAdapter(@NonNull Context context, int child_layout_id, @NonNull List<ResouceBean> objects) {super(context, child_layout_id, objects);this.child_layout_id =child_layout_id;}//该方法滚动到屏幕就会调用执行@NonNull@Overridepublic View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {ResouceBean bean = getItem(position);Log.d("ImageTextAdapter 图片ID:",bean.getImageId()+"");//子布局及布局的组件,convertView缓存了子布局View child_layout;//内部类,创建对象后存储起来RecyclerViewHolder recyclerViewHodler;if (convertView==null){child_layout = LayoutInflater.from(getContext()).inflate(child_layout_id,parent,false);recyclerViewHodler=new RecyclerViewHolder();recyclerViewHodler.imageView=child_layout.findViewById(R.id.list_view_image);recyclerViewHodler.textView=child_layout.findViewById(R.id.list_view_text);child_layout.setTag(recyclerViewHodler);}else {child_layout=convertView;}recyclerViewHodler=(RecyclerViewHolder)child_layout.getTag();ImageView iv = recyclerViewHodler.imageView;TextView text =recyclerViewHodler.textView;iv.setImageResource(bean.getImageId());text.setText(bean.getName());return child_layout;}class RecyclerViewHolder{ImageView imageView;TextView textView;}

4、listView子布局组件点击事件

listView绑定适配器后,通过通过setOnItemClickListener设置监听事件.

ListViewActivity.class 的oncreate()完整代码:

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_llist_view);//数组填充数据List<ResouceBean> data = new ArrayList<ResouceBean>();for(int i=0;i<100;i++){ResouceBean bean = new ResouceBean("测试"+i,R.drawable.test);data.add(bean);}//数据适配器,指定了显示的action,以及listview里面的子布局ImageTextAdapter adapter = new ImageTextAdapter(this,R.layout.list_view_child_layout,data);ListView lv = findViewById(R.id.list_view);lv.setAdapter(adapter);//事件lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {ResouceBean bean=data.get(position);Toast.makeText(ListViewActivity.this,bean.getName(),Toast.LENGTH_SHORT).show();}});}

14.滚动控件RecyclerView

1、listview效果及横向滑动

listview只能纵向滚动,不能横向滚动.andorid提供了一个更加大的控件recyclerView.
recylerView是listview增强版本,目前官方推荐使用recylerView.

要实现listview 图形+文字的同样效果,所以直接使用上面例子的子布局和资源.

1、创建RecylcerViewActivity及布局

创建RecylcerViewActivity及布局,布局中包括recylerview控件.

activity_recylcer_view.xml布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".RecylcerViewActivity"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerViewid"android:layout_width="match_parent"android:layout_height="match_parent"/></androidx.constraintlayout.widget.ConstraintLayout>

RecylcerViewActivity.class先创建,等一下填充代码。

2、 创建适配器
RecylerViewAdapter.class代码:


public class RecylerViewAdapter extends RecyclerView.Adapter<RecylerViewAdapter.InnViewHolder> {private List<ResouceBean> bean = new ArrayList<>();static class InnViewHolder extends RecyclerView.ViewHolder{ImageView imageView;//list item图片TextView textView;//list item文字public InnViewHolder(@NonNull View itemView) {super(itemView);imageView=itemView.findViewById(R.id.list_view_image);textView=itemView.findViewById(R.id.list_view_text);}}public RecylerViewAdapter(List<ResouceBean> data){bean=data;Log.d(this.getClass().toString()+"初始化",data.size()+"");}@Overridepublic InnViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view  = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_view_child_layout,parent,false);InnViewHolder holder = new InnViewHolder(view);return holder;}@Overridepublic void onBindViewHolder(@NonNull InnViewHolder holder, int position) {ResouceBean resb = bean.get(position);Log.d(this.getClass().toString(),resb.getName()+">>>>");holder.textView.setText(resb.getName());holder.imageView.setImageResource(resb.getImageId());}@Overridepublic int getItemCount() {return bean.size();}
}

解释:
1.RecylerViewAdapter继承自RecyclerView.Adapter<RecylerViewAdapter.InnViewHolder>,其中RecylerViewAdapter.ViewHolder是该类的一个静态内部类.

2.bean存储传过来的图片,文本数据.

3.InnViewHolder是静态内部类,接受子布局,获取子布局控件对象.

4.RecylerViewAdapter构造函数接受传递过来的图片文本数据.

5.重写onCreateViewHolder,获取子布局,并传递给InnViewHolder内部类.

6.重写onBindViewHolder,给子布局控件设置图片及文字.

7.getItemCount获取数据的长度

需要注意的是,R.layout.list_view_child_layout子布局的跟布局一定要设置一个高度,或者选择高度选择wrap_content,不然一个item就会占满屏幕.

3、修改RecylcerViewActivity

@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_recylcer_view);//数组填充数据List<ResouceBean> data = new ArrayList<ResouceBean>();for(int i=0;i<100;i++){ResouceBean bean = new ResouceBean("测试"+i,R.drawable.test);data.add(bean);}RecyclerView recyclerView=findViewById(R.id.recyclerViewid);LinearLayoutManager layoutManager = new LinearLayoutManager(this);//横向滑动//layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);recyclerView.setLayoutManager(layoutManager);RecylerViewAdapter adapter = new RecylerViewAdapter(data);recyclerView.setAdapter(adapter);}

解释:
1.初始化数据,创建RecyclerView组件

2.给recyler布局创建一个布局管理器

3.将数据传递给适配器,与recyler适配

4.横向滑动:layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

RecyclerView布局切换

RecyclerView使用不同的布局管理器,很容易实现不同的展现效果.

        //线性布局LinearLayoutManager layoutManager = new LinearLayoutManager(this);//layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);//网格布局GridLayoutManager grild = new GridLayoutManager(this,2);//grild.setOrientation(GridLayoutManager.HORIZONTAL);//瀑布流布局StaggeredGridLayoutManager sgrild= new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);recyclerView.setLayoutManager(sgrild);

recylerView事件

recylerView没有直接提供事件,而是子布局控件直接设置监听事件. recylerView的子布局是在adapter绑定子布局及获取控件的,所以直接在获取控件后,直接设置事件.

RecylerViewAdapter.class 修改onCreateViewHolder方法,控件增加事件的注册.


public class RecylerViewAdapter extends RecyclerView.Adapter<RecylerViewAdapter.InnViewHolder> {private List<ResouceBean> bean = new ArrayList<>();static class InnViewHolder extends RecyclerView.ViewHolder{ImageView imageView;//list item图片TextView textView;//list item文字public InnViewHolder(@NonNull View itemView) {super(itemView);imageView=itemView.findViewById(R.id.list_view_image);textView=itemView.findViewById(R.id.list_view_text);}}public RecylerViewAdapter(List<ResouceBean> data){bean=data;Log.d(this.getClass().toString()+"初始化",data.size()+"");}@Overridepublic InnViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view  = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_view_child_layout,parent,false);InnViewHolder holder = new InnViewHolder(view);//item点击事件holder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int position = holder.getAdapterPosition();Toast.makeText(v.getContext(),position+"----",Toast.LENGTH_SHORT).show();}});//子布局控件事件holder.imageView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//当前itemint position = holder.getAdapterPosition();Toast.makeText(v.getContext(),bean.get(position).getImageId(),Toast.LENGTH_SHORT).show();}});holder.textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int position = holder.getAdapterPosition();Toast.makeText(v.getContext(),bean.get(position).getName(),Toast.LENGTH_SHORT).show();}});return holder;}@Overridepublic void onBindViewHolder(@NonNull InnViewHolder holder, int position) {ResouceBean resb = bean.get(position);Log.d(this.getClass().toString(),resb.getName()+">>>>");holder.textView.setText(resb.getName());holder.imageView.setImageResource(resb.getImageId());}@Overridepublic int getItemCount() {return bean.size();}
}

解释:

  1. int position = holder.getAdapterPosition();获取到当前item

15.recylerView作为微信聊天UI

recylerView使用有点复杂,所以本例子主要目的是熟悉recylerView的使用流程.

1.总体布局:

微信的聊天UI上面部分是内容,用来显示聊天的内容,所以是个容器.下面是消息输入框和发送按钮.

UI布局思路,root布局为垂直布局,上部分为聊天的容器,使用recylerView,底部用线性布局,左侧一个输入框,右侧为发送按钮.

另外还需要一个子布局,用来显示每条消息.然后动态加入到recylerView中.

2.具体流程:
使用recylerView作为内容容器.通过发送按钮,将消息输入框的内容动态加入到list中,然后将数据传递个适配器,适配器将数据和消息记录子布局绑定,recylerView在绑定适配器,这样容器就会显示发送的消息.

下面是具体的实现:

1.创建MessageActivity,进行布局:

先不看MessageActivity代码,先看一下布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MessageActivity"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!--用来显示消息--><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/messagebox"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/><!--发送消息表单--><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_height="80dp"android:layout_width="match_parent"android:orientation="horizontal"><EditTextandroid:id="@+id/message_text"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:maxLines="2"/><com.google.android.material.button.MaterialButtonandroid:id="@+id/sendmessage_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="发送"/></LinearLayout></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

2.创建子布局:

然后在创建一个子布局message_item_layout:
子布局里面有一个线性布局,背景是Nine-Patch图片,是个消息框.里面包含一个文本控件.

<?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"><LinearLayoutandroid:layout_gravity="right"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/message"><TextViewandroid:id="@+id/message_item"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="0dp"android:paddingLeft="0dp"android:layout_marginRight="10dp"/></LinearLayout></LinearLayout>

Nine-Patch 图片是可以拉伸的图片,可以通过android studio创建,具体做法是选中一个图片,右键选择create-9-patch file.然后可以编辑.

具体的编辑是告诉android那边可以拉伸,哪些不能拉伸,可以拉伸的像素用边框点黑色的点.

上面的点:意思是横向拉伸会复制这个垂直的像素.

左侧的点:意思是纵向拉伸时,可以复制的横向条形像素.

下方的点:黑点连成的线条,意思是文本显示的宽度区域.

右侧的点:黑点连城的线条,意思是文本可以显示的高度区域.

3.创建适配器

我们的数据很简单,只是一个消息,字符串. 适配器必须继承自 RecyclerView.Adapter<MessageAdaptger.InnViewHolder>,其中InnViewHolde是个内部类,内部类用来初始化创建子布局的控件.

适配件内部创建一个list属性,用来存储消息.

然后通过onCreateViewHolder()来创建子布局,将子布局传递给InnViewHolder,InnViewHolder来完成子布局初始化.

通过onBindViewHolder()方法获取当前list中的记录,并且通过InnViewHolder类型的参数,来绑定消息.

具体代码如下:


public class MessageAdaptger extends RecyclerView.Adapter<MessageAdaptger.InnViewHolder> {ArrayList<String> data =null;public MessageAdaptger(ArrayList list){data=list;}//完成子布局控件的创建static class InnViewHolder extends RecyclerView.ViewHolder{TextView text;public InnViewHolder(@NonNull View itemView) {super(itemView);text=itemView.findViewById(R.id.message_item);}}//完成子布局创建@NonNull@Overridepublic InnViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view  = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_item_layout,parent,false);InnViewHolder holder = new InnViewHolder(view);return holder;}//获取当前显示的list记录,并绑定到子布局控件中@Overridepublic void onBindViewHolder(@NonNull InnViewHolder holder, int position) {String resb =(String) data.get(position);Log.d(this.getClass().toString(),resb+">>>>");holder.text.setText(resb);}@Overridepublic int getItemCount() {return data.size();}
}

4.完善MessageActivity

package com.example.myapplication;import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;import java.util.ArrayList;
import java.util.List;public class MessageActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_message);//保存数据ArrayList<String> data = new ArrayList<String>();//线性布局RecyclerView messagebox= findViewById(R.id.messagebox);LinearLayoutManager layoutManager = new LinearLayoutManager(this);messagebox.setLayoutManager(layoutManager);//发送数据,将输入数据绑定到RecyclerViewEditText text = findViewById(R.id.message_text);Button send_button = findViewById(R.id.sendmessage_button);send_button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String message=text.getText().toString();data.add(message);MessageAdaptger adaptger= new MessageAdaptger(data);messagebox.setAdapter(adaptger);}});}
}

实际微信分为自己发的,和接收到信息.自己发的在右侧,别人发的在左侧. 如何将发送的,接受的分别显示呢,只要重写适配器中的getItemViewType()方法即可. 前提是消息记录需要是对象,有type类型字段.用来区分是发还是收.

public void getItemViewType(int position ){int item = data.get(position);return item.type;
}

然后在onCreateViewHolder()方法中,viewType就是item.type参数.

2.android布局及UI控件相关推荐

  1. android ui界面组件,说说 Android 的常见 UI 控件

    这些控件都有一些共有属性,让我们来看看吧: 共有属性 说明 android:id 唯一标识符 android:layout_width 宽度 android:layout_height 高度 andr ...

  2. android基础ui控件,Android基础——基础UI控件

    日历,时钟,计时器 package com.example.mybaseuii; import androidx.appcompat.app.AppCompatActivity; import and ...

  3. android布局 哪个控件在最上层_Android 在最上层添加悬浮View(兼容Android 8.0)

    记着在很久以前写Android的时候做一个在最上层悬浮的一个View非常容易,什么权限啊什么的根本没有那么多限制,,但今天试着写了一下发现处处碰壁,出现了各种各样的问题,后来在网上看了一些资料,发现现 ...

  4. Android UI控件和布局

    说明: 本文是郭霖<第一行代码-第3版>的读书笔记 4.1 如何编写程序界面 编写XML,这是传统的方法 ConstraintLayout,Google推出的新方法,可以在可视化编辑器中拖 ...

  5. Android 通过代码改变控件的布局方式

    在很多情况下当我们在xml中布局的方式并不能满足我们的要求,而这时我们就需要通过在代码中控制控件的布局 根据不同的条件来控制布局.首先来了解一下安卓中的一些单位 dip: device indepen ...

  6. android 画布裁剪,一种基于Android系统对UI控件进行轮廓剪裁及美化的方法与流程...

    本发明涉及Android应用的技术领域,特别涉及一种基于Android系统对UI控件进行轮廓剪裁及美化的方法. 背景技术: 目前,随着智能电视的普及,Android应用层出不穷,而那些表现形式单一.传 ...

  7. android通过代码设置铃声_第六十四回:Android中UI控件之SeekBar

    各位看官们,大家好,上一回中咱们说的是Android中UI控件之ProgressBar的例子,这一回咱们的例子是UI控件之SeekBar.闲话休提,言归正转.让我们一起Talk Android吧! 看 ...

  8. android listview 滑动条显示_第七十六回:Android中UI控件之RecyclerView基础

    各位看官们,大家好,上一回中咱们说的是Android中UI控件之ListView优化的例子,这一回咱们说的例子是UI控件之RecyclerView.闲话休提,言归正转.让我们一起Talk Androi ...

  9. android 获取控件高度_安卓开发入门教程UI控件_ProgressBar

    什么是ProgressBar ProgressBar是用于提示用户进行等待的UI控件,. 基础样例 1.loading图 效果图 代码 布局文件代码 <ProgressBarandroid:id ...

最新文章

  1. Intel Optane PMEM 概览
  2. 成功解决ImportError: cannot import name ‘joblib‘
  3. 在Kubernetes上运行SAP UI5应用(下): 一个例子体会Kubernetes内容器的高可用性和弹性伸缩
  4. wordpress程序安装php多少,2020最新WordPress网站程序详细安装教程
  5. 一步一步写算法(之排序二叉树)
  6. 利用Visual Studio Project自动将数据加载到SQL Server数据库中
  7. 海思35系列型号排行_11月手机性能排行榜:小米10至尊纪念版排名第三
  8. python生成pdf报告模块_python生成pdf报告、python实现html转换为pdf报告
  9. 小米MIX 2最简单卡刷开发版启用root权限的方法
  10. bzoj 3332 旧试题
  11. 猛文:关于中国歼20气动性能…
  12. 在团购网上空手赚钱项目,你敢做就敢赚!
  13. 科幻作品中强大的计算机和人工智能有哪些?
  14. NAudio:MP3转WAV和Wav转Mp3
  15. window10 多桌面切换快捷键 win+tab
  16. 北京中医药大学计算机应用基础作业1,北京中医药大学远程教育“计算机应用基础”第5次作业.doc...
  17. Centos 下解压和压缩rar文件
  18. 乐山计算机学校学籍管理,乐山计算机学校学生管理系统设计与实现
  19. Jenkins的全量迁移
  20. Qt Mainwindow添加/删除标题栏

热门文章

  1. 20230331华清远见作业
  2. linux pclint配置_pclint设置 | 学步园
  3. 软件项目管理第4版课后习题[附解析]第十四章
  4. excel同一单元格怎么换行_excel表格怎么换行?excel表格中怎么换行?
  5. 从京东家电十年,看中国家电产业三大变革
  6. 学会这10种实用的定时任务,拿捏所有业务场景
  7. 配置samba服务实现Linux(CentOS7)与Windows之间的文件共享
  8. 中国大学慕课 大连理工大学 C语言程序设计 第四周编程作业 选择结构程序设计
  9. 七牛云配置CDN,阿里云,ERROR: ACCESS DENIED,访问失败
  10. KL 散度和白化(球化)算法