1、内容主要参考自:https://www.bilibili.com/video/BV1Dt411L74N
2、这部分的内容,主要是跟着视频做例子走的,如果有不对的,希望可以指出或补充。
3、完成了类似于列表视图(ListView)、网格视图(GridView)以及瀑布流视图的效果。
4、新知识。
循环器视图(RecyclerView)能够实现这些功能(如):横向滚动的ListView、横向滚动的GridView、瀑布流控件。
Android 控件 RecyclerView
1、各个部分id名称定义成便于识别且好记的。
2、在复制更改相似代码的时候,注意不同点的更改,尤其是id名称。
3、要有一个整体的思路。
一定要注意细节问题。
报错显示的错误地方(如图框框里的)有可能只是受到了影响,不是主要原因。
找bug的方法是找caused by开头的,从下往上找(转)。
1、在完成了ListView视图效果部分的时候,进行运行时,出现如下显示的错误。
尝试自己看它对应的报错部分,没有发现问题,然后开始百度,也没找到正确的解决方法。
突然想到会不会是导包问题,果然。
再找到对应的。
删掉标出来的框框里的内容就可以了!
先把需要用到的文件以及图片素材,建好放好。
注:
1.为了明显的展示出瀑布流视图的效果,所以准备了两张不同大小的图片(一个横向、一个竖向的)。
2.这里采用的自定义适配器(继承基适配器)。
这部分相当于是一个界面的交互窗口,连接着各个选项对应着的效果。
① 列表视图效果部分(网格视图效果部分、 瀑布流视图效果部分同理,复制更改就行)。
<item
android:id="@+id/list_view"
android:title="ListView效果">
<menu>
<item
android:id="@+id/list_view_v"
android:title="垂直" />
<item
android:id="@+id/list_view_v2"
android:title="垂直反向" />
<item
android:id="@+id/list_view_h"
android:title="水平" />
<item
android:id="@+id/list_view_h2"
android:title="水平反向" />
menu>
item>
② 菜单栏效果,如下。
实现的视图效果都会引用到的部分。
1、首先来看数据构造的部分(datas文件夹),如下:
① 每个条目都是由图片+标题组成的。
图片数量任意多少都可以。为便于展现瀑布流视图参差不齐的效果,图片(横向和竖向的图片)是间隔插入的。
2、布局部分(layout文件夹),如下:
在所有的布局上,整体都采用的是相对布局(也可以用别的方式),为了效果展示明显些,将这里的背景颜色和其他布局中的测试标题的字体颜色
设成差别较大的颜色。
① 主布局部分,也就是引用RecyclerView控件的地方。
3、设配器部分(adapters文件夹),如下:
① BaseAdapter,其他几个都会继承这个的。基本适配器。有了这个就可以大大减少代码量了。
package com.example.testrecyclerview.adapters;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.example.testrecyclerview.R;
import com.example.testrecyclerview.datas.EachItem;
import java.util.List;
public abstract class BaseAdapter extends RecyclerView.Adapter<BaseAdapter.InnerHolder> {
//成员变量 都可以调用
private final List<EachItem> datas;
//数据设置进来
public BaseAdapter(List<EachItem> data){
this.datas = data;
}
//创建条目
@Override
public BaseAdapter.InnerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//sub自定义
View view = getSubView(parent, viewType);
return new InnerHolder(view);
}
protected abstract View getSubView(ViewGroup parent, int viewType);
//绑定holder的,一般是用来设置参数
@Override
public void onBindViewHolder(BaseAdapter.InnerHolder holder, int position) {
//设置参数
holder.setData(datas.get(position));
}
//返回条目个数
@Override
public int getItemCount() {
if (datas != null) {
return datas.size();
}
return 0;
}
public class InnerHolder extends RecyclerView.ViewHolder{
//成员变量
private ImageView iconMy;
private TextView titleMy;
public InnerHolder(View itemView){
super(itemView);
//找到条目控件
//也就是找到统一好了的id名称
iconMy = itemView.findViewById(R.id.icon);
titleMy = itemView.findViewById(R.id.title);
}
//设置数据的
public void setData(EachItem itemBean) {
//设置参数
iconMy.setImageResource(itemBean.img);
titleMy.setText(itemBean.title);
}
}
}
1、实现列表视图效果的布局部分(item_list_view.xml)。
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="110dp">
<ImageView
android:id="@+id/icon"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_margin="10dp"
android:scaleType="fitXY"
android:src="@mipmap/test_img" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="150dp"
android:text="测试标题"
android:textSize="30sp" />
RelativeLayout>
androidx.cardview.widget.CardView>
RelativeLayout>
以上的效果如下:
2、 连接列表视图布局的(ListViewAdapter)。
其他几个视图适配器同理设置,如下的框框部分就是需要更改的点(改成相对应的名称)。
GridView效果以及瀑布流效果的实现略。
① 运行主窗口(MainActivity.java)
这里实现了:模拟数据,加载菜单并点击实现相应的点击事件,ListView、GridView以及瀑布流的水平垂直正向反向的布局效果。
package com.example.testrecyclerview;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import com.example.testrecyclerview.adapters.GridViewAdapter;
import com.example.testrecyclerview.adapters.ListViewAdapter;
import com.example.testrecyclerview.adapters.StaggerAdapter;
import com.example.testrecyclerview.datas.DatasImg;
import com.example.testrecyclerview.datas.EachItem;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView listMy;
private List<EachItem> datas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//调用主界面
setContentView(R.layout.layout_main);
//找到recyclerview控件
listMy = (RecyclerView) this.findViewById(R.id.recycler_view);
//数据准备 模拟数据
initData();
//设置默认的显示样式为ListView
showList(true,false);
}
//模拟数据
private void initData(){
//创建数据集合
datas = new ArrayList<>();
//创建模拟数据
for (int i = 0; i < DatasImg.icons.length; i++) {
//数据对象
EachItem data = new EachItem();
data.img = DatasImg.icons[i];
data.title = i+"只猫";
//添加到集合里面
datas.add(data);
}
}
//加载菜单的
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//一个参数用于指定通过什么资源文件来创建菜单,第二个参数用于指定菜单项添加到哪一个Menu对象当中。
getMenuInflater().inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
//菜单点击事件
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
switch (itemId){
//ListView效果
case R.id.list_view_v:
showList(true,false);
break;
case R.id.list_view_v2:
showList(true,true);
break;
case R.id.list_view_h:
showList(false,false);
break;
case R.id.list_view_h2:
showList(false,true);
break;
//网格效果
case R.id.grid_view_v:
showGrid(true,false);
break;
case R.id.grid_view_v2:
showGrid(true,true);
break;
case R.id.grid_view_h:
showGrid(false,false);
break;
case R.id.grid_view_h2:
showGrid(false,true);
break;
//瀑布流效果
case R.id.stagger_view_v:
showStagger(true,false);
break;
case R.id.stagger_view_v2:
showStagger(true,true);
break;
case R.id.stagger_view_h:
showStagger(false,false);
break;
case R.id.stagger_view_h2:
showStagger(false,true);
break;
}
return super.onOptionsItemSelected(item);
}
//用于显示ListView效果
private void showList(boolean isVertical,boolean isReverse) {
//设置布局管理器(样式)
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//设置水平/垂直
//设置一个布局管理器来控制
layoutManager.setOrientation(isVertical?
LinearLayoutManager.VERTICAL:LinearLayoutManager.HORIZONTAL);
//默认是正向的(左到右,上到下)
// 设置反向
// 滑动方向
layoutManager.setReverseLayout(isReverse);
listMy.setLayoutManager(layoutManager);
//创建适配器
ListViewAdapter adapter = new ListViewAdapter(datas);
//设置到RecyclerView控件里面去
listMy.setAdapter(adapter);
}
//用于显示GridView效果
private void showGrid(boolean isVertical,boolean isReverse) {
//创建布局管理器
GridLayoutManager layoutManager = new GridLayoutManager(this,3);
//设置水平/垂直
layoutManager.setOrientation(isVertical ?
LinearLayoutManager.VERTICAL:LinearLayoutManager.HORIZONTAL);
//反向
layoutManager.setReverseLayout(isReverse);
//设置布局管理器
listMy.setLayoutManager(layoutManager);
//创建适配器
GridViewAdapter adapter = new GridViewAdapter(datas);
//设置到RecyclerView控件里面去
listMy.setAdapter(adapter);
}
//实现瀑布流效果
private void showStagger(boolean isVertical,boolean isReverse) {
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2,
isVertical?StaggeredGridLayoutManager.VERTICAL:StaggeredGridLayoutManager.HORIZONTAL);
layoutManager.setReverseLayout(isReverse);
listMy.setLayoutManager(layoutManager);
StaggerAdapter adapter = new StaggerAdapter(datas);
listMy.setAdapter(adapter);
}
}
② 运行效果(部分)如下:
完整代码链接(百度网盘):https://pan.baidu.com/s/1fRtVsQFuBID9JaJ9lv2E2A
提取码:0vyp