常见控件的使用方法
1.TextView
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/text_view"
android:gravity="center"
android:textSize="24sp"
android:textColor="#00ff00"
android:text="UI第一步"
/>
都是在xml文件中处理的,
android:gravity=“center” :负责处理布局文字的对齐方式(位置),可选值有top,button ,left,right,center 等
android:textSize=“24sp” :负责处理文字的大小
android:textColor=“#00ff00” :负责处理文字的颜色
2.Button
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id ="@+id/button1"
android:text="按钮"
android:textAllCaps="false"
/>
注意这里文本内容中的英文字母会被系统自动转换为大写,若想保留小写英文可以,自己关闭这一默认特性 android:textAllCaps=“false”
可以在活动中获取实例,为点击事件注册监听器,这里注册方法可以选择内部类或者是接口
3.EditText
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/edit_text"
android:hint="Type something here"
android:maxLines="2"
/>
这个小控键可以制作一个输入框
android:hint=“Type something here”:可以在输入框提升Type something here,这段文字
android:maxLines=“2”:前面设置高度的时候设置的是,随着文本变化而变化,高度是可变的,这个可以限定他最大伸缩为俩行
public void onClick(View view) {
if(view.getId()==R.id.button1)
{
String inputText =editText.getText().toString();
Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_SHORT).show();
}
}
前面有学习过toast,这里可以将其与输入框结合,即输入框输入什么,在toast就提示什么
4.lmageView
lmageView是负责在界面展示图片的一个控件
!!!图片一般放在drawable开头的目录下的,目前项目中有一个空的drawable目录,不过该目录没有指定具体的分辨率,所以一般不使用他来放置图片
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/image_view"
android:src="@drawable/img_1"/>
这里因为图片的高和宽都是未知的所以高和宽都是自适应
android:src=“@drawable/img_1”/>:该属性为这个控件的指定图片
与按钮结合可以利用按钮更换图片
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(view.getId()==R.id.button1)
{
imageView.setImageResource(R.drawable.img_2);
}
}
});
5.ProgressBar
ProgressBar用在界面中显示一个进度条表示程序正在加载
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:max="100"
/>
他会默认设置一个圆形的进度条,他在不断旋转,如何在数据加载结束时使进度条消失呢,这里就考虑到控件的可见属性,所有的android控件都有这个属性,Android:visibility 他的可选择值有三种,visible ,invisible ,gone, visible表示该控件可见,这个是默认值,invisible表示不可见但是仍然占据原来的位置和大小,gone表示控件不可见,同时不占据任何屏幕大小,我们可以通过方法控制控件的可见性,这里使用的是setVisibility()方法,可以传入View.VISIBLE ,View.INVISIBLE,View.GONE三个值
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(view.getId()==R.id.button1)
{
if(progressBar.getVisibility()==View.GONE)
{
progressBar.setVisibility(View.VISIBLE);
}
else
{
progressBar.setVisibility(View.GONE);
}
}
}
});
这里判断如果其可见就将其变为不可见,如果其不可见就将其变为可见
style="?android:attr/progressBarStyleHorizontal"
android:max="100"
这个Style可以修改进度条的样式,可以将其修改为水平进度条
max可以给进度条设置一个最大值,这样可以在代码中动态的修改精度条进度
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(view.getId()==R.id.button1)
{
int progress = progressBar.getProgress();
progress= progress+10;
progressBar.setProgress(progress);
}
}
});
点击按钮就获取精度条的当前精度,然后加10 后作为更新进度
6.AlertDialog
该控件负责控制弹出对话框,对话框是置顶与所有界面元素之上的,可以屏蔽其他控件的交互能力,
注意:他的代码是写在活动中的,并没有写到布局文件中具体代码如下
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("上班日记");
dialog.setMessage("又是上班就期待下班的一天");
dialog.setCancelable(false);
dialog.setPositiveButton("ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which){
}
});
dialog.setNegativeButton("no", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
}
});
dialog.show();
}
});
他通过lertDialog.Builder注册了一个AlertDialog的实例,然后处理他的标题 ,内容, 是否可以使用back键关闭等属性
在下面,通过 dialog.setPositiveButton和 dialog.setNegativeButton设置了对话框的俩个按钮,这方法前面对应按钮中的文本内容,后面负责其管理的响应事件
最后通过show方法将对话框展示出来
7.ProgressDialog
ProgressDialog和AlertDialog有点类似 ,都是弹出一个对话框,阻断其他控件的交互能力,不过他会显示一个进度条,表示当前操作比较耗时,处理方法和上一个类似都是在活动中处理
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ProgressDialog progress= new ProgressDialog(MainActivity.this);
progress.setTitle("下班进行中");
progress.setMessage("下班中");
progress.setCancelable(true);
progress.show();
}
});
有一个小注意点,如果在 progress.setCancelable(true);中传入false,那么该数据框就必须通过 progress.dismiss()来关闭对话框,否则将无法关闭
四种布局
布局就是一种可于放置多个控件的容器他可以按照一定规律调整内部控件的位置,布局内部也可以放置布局
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FW3V4mks-1690111407234)(E:\笔记\笔记内图片\QQ截图20230718110457.png)]
1.线性布局
LinearLayout又叫线性布局,他会将她包含的控件,在线性方向上依次排列
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button1"
android:text="nutton1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="nutton2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button3"
android:text="nutton3"/>
</LinearLayout>
android:orientation=“horizontal”:这个属性可以控制他在水平或者竖直上排序,为horizontal是水平上排序 vertical是竖直上排序
android:layout_gravity s 指定控件在布局中的对齐方式,注意他的对齐方式只有在非布局约束方向才能起作用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:id="@+id/button1"
android:text="nutton1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:id="@+id/button2"
android:text="nutton2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:id="@+id/button3"
android:text="nutton3"/>
</LinearLayout>
android:layout_weight:是按比例来控制指定按键的大小,如下
<EditText
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/input_message"
android:hint ="Type someing"/>
<Button
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/button3"
android:text="nutton3"/>
这俩个控键的宽都是0dp,这是因为这辆个控件都使用了layout_weight,他的优先级高于layout_width,同时为什么这里设置是1(效果是1:1平均分配),这里解释一下该方法的分配方法,他会把布局中所有控件下的layout_weight相加,然后计算每个控件所占的比例进行分配
它可以通过指定部分控件进行控制如下
<EditText
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:id="@+id/input_message"
android:hint ="Type someing"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button3"
android:text="nutton3"/>
他的效果就是按钮正常按文本大小自适应,其余的空间由输入框填满
2.相对布局
RelativeLayout又叫相对布局,他和线性布局相比他更加随意,它可以使控件出现到任何位置,所以他的属性比较多
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button1"
android:text="button1"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
android:text="button2"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button3"
android:text="button3"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button4"
android:text="button4"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button5"
android:text="button5"
android:layout_centerInParent="true"
/>
效果如下[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WOEDrqq0-1690111407235)(E:\笔记\笔记内图片\微信图片_20230718144741.jpg)]
与父布局的左上,右上,左下,右下,中央对齐,他的每个控件都是 相对于父布局进行的,这里可不可以根据控件的相对位置进行布局,也可以的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RaIxed8p-1690111407235)(C:\Users\32117\AppData\Roaming\Typora\typora-user-images\image-20230718145820195.png)]
above表示该代码在目标控件上面
below表示该控件在目标控件下面
toLeftof表示该控件在目标控件左侧
toRighrof表示该控件在目标控件右侧
因为这里定位用到了目标控件所以目标控件要在这些控件之前定义
3.帧布局
FrameLatout又叫帧布局,他相比较前面的布局他比较简单,他的控件好默认摆放到布局的左上角
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="想下班,不想干活,想贴贴"/>
<ImageView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@mipmap/ic_launcher"/>
</FrameLayout>
这里也可以使用android:layout_gravity控制控件对齐方式
4.百分比布局
前面三个布局中,除了线性布局可以按照比例控制控件大小其他俩种都无法做到,为此android引入了百分比布局,在百分比布局中不在使用wrap_content和math_parent控制控件大小,而是直接指定控件在布局中的占比,这样就可以实现按比例控制控件大小
不过因为线性布局已经可以实现,所以百分比布局只为后俩种做了功能扩展,提供了PercentFrameLayout和PercentRelativeLayout
因为他是后来补充的,为了使他在所有android版本中正常使用,开发团队将其定义到了support库中,只需要在项目的build.gradle中添加百分比布局的依赖,这样保证百分比布局的兼容性
自定义控件
控件的继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uK903oQC-1690111407236)(E:\笔记\笔记内图片\QQ截图20230718163634.png)]
我们使用的所有是控件都是继承于View的,所有的布局都是继承于ViewGroup。
引入布局
核心;就是在一个xml文件中通过include将一个布局文件导入另一个文件
<?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=".MainActivity">
<include layout="@layout/title"/>
</androidx.constraintlayout.widget.ConstraintLayout>
核心就是
注意:这里又将如何取消系统自带的标题栏
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar=getSupportActionBar();
if(actionBar!=null)
{
actionBar.hide();
}
}
这里有getSupportActionBar得到了一个ActionBar实例,又通过他调用hide隐藏了标题栏
创建自定义控件
引入布局的技巧确实解决了重复编写布局代码的问题,但是如果布局中有一些控件要求 能够响应事件,我们还是需要在每个活动中为这些控件单独编写一次事件注册的代码。比如 说标题栏中的返回按钮,其实不管是在哪一个活动中,这个按钮的功能都是相同的,即销毁 掉当前活动。而如果在每一个活动中都需要重新注册一遍返回按钮的点击事件,无疑又是增 加了很多重复代码,这种情况最好是使用自定义控件的方式来解决。
核心 在一个类中把自定义的控件设置好,在xml文件中直接导入
public class titleLayout extends LinearLayout {
public titleLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.title,this);
Button button = (Button) findViewById(R.id.butt_back);
Button button1 = (Button) findViewById(R.id.butt_edit);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
((Activity)getContext()).finish();
}
});
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(),"另一个按钮可以关闭要不要试试",Toast.LENGTH_LONG).show();
}
});
}
}
这里新建了一个类,他继承于LinearLayout,重写了LinearLayout函数进行构造,在构造中进行了动态的加载,这里利用了 LayoutInflater实现,通过他的from方法可以构建出一个 LayoutInflater的对象,然后调用inflate方法动态的加载一个布局文件,该方法中加载俩个参数,第一个是要加载的布局文件参数,一个是给加载好的布局一个父布局
<com.example.zidingyikj.titleLayout
android:layout_width="match_parent"
android:layout_height="200dp"/>
这里进行了导入,这里需要指明控件的完整类名,包名不可省略
Button button = (Button) findViewById(R.id.butt_back);
Button button1 = (Button) findViewById(R.id.butt_edit);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
((Activity)getContext()).finish();
}
});
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(),"另一个按钮可以关闭要不要试试",Toast.LENGTH_LONG).show();
}
});
ListView
以列表的形式展示数据内容,并且能够根据列表的高度自适应屏幕显示
划窗,例如淘宝的购物界面,可以使用户通过手指上下滑动的方式将屏幕外的数据滚到屏幕内
1.简单使用LIstView
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/list_view"/>
首先,在xml文件中加入ListView 控件,将其的宽和高都设为自适应这样他就会占满整个布局的空间
private String[] data={"Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","CHerry","Mango","Apple","Banana","Orange","Watermelon","Pear","Grape","Pineapple","Strawberry","CHerry","Mango"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_text);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(listText.this, android.R.layout.simple_list_item_1,data);
ListView listView =(ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
其次开始在活动中使用该控件,ListView是用来展示大量数据的,,所以需要我们提供数据给他,数据可以来自网上,来自数据库,这里用一个简单的数组进行测试
数组无法直接传递数据给ListView,我们还需要借助适配器来完成,android提供了很多适配器的实现类,这里使用其中的一个Arrayadapter,它可以通过泛型指定要匹配的数据类型,在构造函数中把适配的数据传入,ArrayAdapter有多个构造函数重载,这里因为我们提供的数据都是字符串,因此将其泛型指定为String 然后在构造函数中依次传入当前上下文,ListView 子项布局的id,和要适配的数据 ,这里使用了android.R.layout.simple_list_item_1作为子项布局的id,这是android内置的布局文件,里面只有一个TextView,可用于简单的显示一段文本 这一步的目标都是创建一个是适配器
创建ListView的实例对象,通过他调用setAdapter方法,将构建好的适配器对象传递进去,这样ListView和数据的关联就已经完成
2.定制ListView的界面(加入图片等)
首先定义一个实体类,作为他的适配器的适配类型
package com.example.list1;
public class Fruit {
private String name;
private int imageId;
public Fruit(String name, int imageId) {
this.name = name;
this.imageId = imageId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
}
然后为他的子项(小条)制定一个自定义的布局,在layout目录下新建xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/fruit_Viewxml"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/fruit_text"
android:layout_marginLeft="10dp"/>
</LinearLayout>
这里设置了一个ImageView用来放入图片,一个TextView用来显示图片对应内容
下一步创建一个自定义的适配器
public class firuitAdapt extends ArrayAdapter<Fruit> {
private int resourceId;
public firuitAdapt(@NonNull Context context, int resource, List<Fruit> objects) {
super(context, resource, objects);
resourceId=resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Fruit fruit =getItem(position);
View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_Viewxml);
TextView fruitname=(TextView) view.findViewById(R.id.fruit_text);
fruitImage.setImageResource(fruit.getImageId());
fruitname.setText(fruit.getName());
return view ;
}
}
这个适配器继承与ArrayAdapter,并且将泛型指定为Fruit,他重写了父类的一组构建函数,用来把上下文,子项布局的id 和数据都传递进来
又重写了getView 方法,这个方法在每个子项被滚到屏幕内的时候会被调用,在该方法中,首先通过 getItem 得到当前向的Fruit实例,然后用 LayoutInflater得到这个子项的布局
这里 LayoutInflater的inflate方法接受的第三个参数只让父布局中声明的layout属性生效,但是不会为这个view添加父布局
调用View的findViewById分别得到IMageView和TextView的实例 ,然后分别调用他们的setImageResource和setText显示,最后把布局返回
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_text);
initFruits();
firuitAdapt adapt = new firuitAdapt(listText.this,R.layout.fruit,fruitList);
ListView listView=(ListView) findViewById(R.id.list_view);
listView.setAdapter(adapt);
}
private void initFruits()
{
for(int i=0;i<2;i++)
{
Fruit apple = new Fruit("苹果",R.drawable.apple);
fruitList.add(apple);
Fruit banana = new Fruit("香蕉",R.drawable.banana);
fruitList.add(banana);
Fruit grape = new Fruit("葡萄",R.drawable.grape);
fruitList.add(grape);
Fruit orange = new Fruit("橙子",R.drawable.orange);
fruitList.add(orange);
Fruit pear = new Fruit("梨",R.drawable.pear);
fruitList.add(pear);
Fruit watermelon = new Fruit("西瓜",R.drawable.watermelon);
3.提升ListView的效率
我们目前的ListView效率是比较低的,因为在getVIew中每次都将布局重新加载了一遍,在ListView快速滚动的时候,他就可能会出现问题,在getView中一个convertView参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用,
Fruit fruit =getItem(position);
View view;
if(convertView==null)
{
view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
}
else
{
view = convertView
}
ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_Viewxml);
TextView fruitname=(TextView) view.findViewById(R.id.fruit_text);
fruitImage.setImageResource(fruit.getImageId());
fruitname.setText(fruit.getName());
return view ;
这里进行了一个判断如果converView不为空,他将继续使用之前的布局,这样提升了他的运行效率
这里每次在getView方法中还是会调用View的findViewById方法来获取一次控件的实例,我们可以借助一个ViewHolder来进一步优化
ListView的点击事件
private List<Fruit> fruitList= new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_text);
initFruits();
firuitAdapt adapt = new firuitAdapt(listText.this,R.layout.fruit,fruitList);
ListView listView=(ListView) findViewById(R.id.list_view);
listView.setAdapter(adapt);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Fruit fruit = fruitList.get(i);
Toast.makeText(listText.this,fruit.getName(),Toast.LENGTH_LONG).show();
}
});
}
核心:使用setOnItemClickListener为ListView为ListView注册了一个监听器,点击子项时就会回调onItemClick方法
更强大的滚动控件——RecyclerView
ListView功能强大,但是他如果不使用一些技巧来提升他的运行效率他的性能就可能比较差,同时他的扩展性用比较差,只能实现竖向滚动,无法实现横向滚动,为此android提供了一个更加强大的滚动控件,他可以说就是一个加强版的ListView
RecyclerView的基本用法
第一步:在app/bulid.gradle文件中在dependencies闭包下添加
implementation 'androidx.recyclerview:recyclerview:1.2.0'
书上的代码无法正常运行
第二步:在activity.xml文件中添加RecyclerView组件
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyle_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
书上的代码无法正常运行
第三步:为适配器准备适配类(即Fruit和fruit.xml),并且把图片复制过来(这个和之前的ListView一样)
第四步:准备一个适配器
public class FruitAdapt extends RecyclerView.Adapter<FruitAdapt.ViewHolder> {
private List<Fruit> mFruitlist;
static class ViewHolder extends RecyclerView.ViewHolder{
ImageView fruitImage;
TextView fruitName;
public ViewHolder(View view)
{
super(view);
fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
fruitName=(TextView) view.findViewById(R.id.fruit_name);
}
}
public FruitAdapt (List<Fruit> fruitlist)
{
mFruitlist = fruitlist;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Fruit fruit =mFruitlist.get(position);
holder.fruitImage.setImageResource(fruit.getImageId());
holder.fruitName.setText(fruit.getName());
}
@Override
public int getItemCount() {
return mFruitlist.size();
}
}
这里定义了一个内部类ViewHoider,ViewHolder继承于RecyclerView.ViewHolder,然后在ViewHolder的构造函数中要传入一个View参数,这个参数就是RecyclerView子项的最外层布局我们可以通过findViewById得到布局中的ImageView和TextView的实例
public FruitAdapt (List<Fruit> fruitlist)
{
mFruitlist = fruitlist;
}
这个构造函数把传过来的数据保存赋值给一个全局变量,
因为 FruitAdapt是继承 RecyclerView.Adapter的,所以要重写下面的三个方法
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Fruit fruit =mFruitlist.get(position);
holder.fruitImage.setImageResource(fruit.getImageId());
holder.fruitName.setText(fruit.getName());
}
@Override
public int getItemCount() {
return mFruitlist.size();
}
第一个函数onCreateViewHolder的目的是创建一个ViewHolderer对象,,在这个方法中加载了friut_xml的布局view=LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit,parent,false);,传到ViewHolder的构造函数中创建了一个ViewHolder实例,最后把这个实例返回
第二个函数onBindViewHolder 会在RecyclerView的子项被滚到屏幕内时给子项的数据赋值,这个方法中,我们通过position得到Fruit的实例,然后将数据设置给holder的fruitImage和fruitName中
第三个函数:告诉RecyclerView一共有多少子项
第五步:在活动中直接调用
private List<Fruit> fruitList= new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();
RecyclerView recyclerView =(RecyclerView) findViewById(R.id.recyle_view);
LinearLayoutManager layoutManager= new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
FruitAdapt adapter = new FruitAdapt(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruits()
{
for(int i=0;i<2;i++)
{
Fruit apple = new Fruit("苹果",R.drawable.apple);
fruitList.add(apple);
Fruit banana = new Fruit("香蕉",R.drawable.banana);
fruitList.add(banana);
Fruit grape = new Fruit("葡萄",R.drawable.grape);
fruitList.add(grape);
Fruit orange = new Fruit("橙子",R.drawable.orange);
fruitList.add(orange);
Fruit pear = new Fruit("梨",R.drawable.pear);
fruitList.add(pear);
Fruit watermelon = new Fruit("西瓜",R.drawable.watermelon);
fruitList.add(watermelon);
}
}
首先:他利用 initFruits();初始化了 initFruits();然后创建 RecyclerView实例。他还创建了一个 LinearLayoutManager,这个是用来指定RecyclerView的布局方式的,这里使用的 LinearLayoutManager是线性布局的意思,然后创建了FruitAdapt的实例,最后调用了setAdapter完成适配器的设置
横向滚动
核心:RecyclerView本身就有横向竖向的属性,这里调用layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); 更改即可
注意横向更改后小配件的许多属性需要改变
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();
RecyclerView recyclerView =(RecyclerView) findViewById(R.id.recyle_view);
LinearLayoutManager layoutManager= new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
FruitAdapt adapter = new FruitAdapt(fruitList);
recyclerView.setAdapter(adapter);
瀑布流布局(网格分布)
小配件的改变自己慢慢品
private List<Fruit> fruitList= new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();
RecyclerView recyclerView =(RecyclerView) findViewById(R.id.recyle_view);
StaggeredGridLayoutManager layoutManager =new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
FruitAdapt adapter = new FruitAdapt(fruitList);
recyclerView.setAdapter(adapter);
核心:StaggeredGridLayoutManager layoutManager =new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); 创建了一个StaggeredGridLayoutManager对象实例他又俩个参数,第一个参数是指定布局是行数,第二个参数是指定他横向或者竖向分布
RecylerView的点击事件
ListView自己设置了子项的点击事件,但是RecyclerView没有设置子项的点击事件,因为ListView虽然直接设置了子项的点击事件但是他如果想处理子项中的某一个按钮,那么就比较麻烦了,这里RecyclerView直接取消了子项的点击事件
ImageView fruitImage;
TextView fruitName;
View fruitview;
public ViewHolder(View view)
{
super(view);
fruitview = view;
fruitImage=(ImageView) view.findViewById(R.id.fruit_image);
fruitName=(TextView) view.findViewById(R.id.fruit_name);
}
}
public FruitAdapt (List<Fruit> fruitlist)
{
mFruitlist = fruitlist;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit,parent,false);
final ViewHolder holder = new ViewHolder(view);
holder.fruitview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit =mFruitlist.get(position);
Toast.makeText(v.getContext(),"你点击了"+fruit.getName(),Toast.LENGTH_LONG).show();
}
});
holder.fruitImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
Fruit fruit =mFruitlist.get(position);
Toast.makeText(v.getContext(),"今天星期三,还没有开始计算机"+fruit.getName(),Toast.LENGTH_LONG).show();
}
});
return holder;
}
这里在ViewHolder中添加了fruitView变量来保存子项最外面的布局,然后在onCreateViewHolder方法中的注册点击事件,在俩个点击事件中,先获取了用户点击的position,然后利用这个难道相应的Fruit实例
<TextView
android:layout_width="match_parent"
android:layout_height="70dp"
android:id="@+id/text"
android:text="计算机"
android:background="@color/blue"
android:textColor="@color/white"
android:textStyle="italic"
android:textSize="40dp"/>