Android之滚动控件Recycler

Activity之滚动控件Recycler

基本用法

RecyclerView 不仅实现了和 ListView 同样的效果,而且还优化了 ListView 存在的各种不足。
RecyclerView 也是新增的控件,以必须先在项目的 build.gradle 中添加相应的依赖库才能使用:

 compile 'com.android.support:recyclerview-v7:24.2.1'

修改布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

这里把宽度和高度都定义为 match_parent,这样 RecyclerView 就能占满整个屏幕。因为 RecyclerView 也不是系统内置的 SDK,所以这里引用的是完整的包路径。

然后为 RecyclerView 创建一个适配器(继承自RecyclerView.Adapter<CatAdapter.ViewHolder>):

public class CatAdapter extends RecyclerView.Adapter<CatAdapter.ViewHolder> {
    private List<Cat> cats;
    static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView image;
        TextView name;
        public ViewHolder(View view) {
            super(view);
            image = (ImageView) view.findViewById(R.id.image);
            name = (TextView) view.findViewById(R.id.name);
        }
    }
    public CatAdapter(List<Cat> cats) {
        this.cats = cats;
    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cat_item, parent, false);
        return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Cat cat = cats.get(position);
        holder.image.setImageResource(cat.getImageId());
        holder.name.setText(cat.getName());
    }
    @Override
    public int getItemCount() {
        return cats.size();
    }
}

先定义了一个内部类 ViewHolder,它继承自 RecyclerView.ViewHolder。然后在 ViewHolder 的构造函数中传入一个 View 参数,它是 RecyclerView 子项的最外层布局,所以我们可以通过它来取得布局中的 ImageView 和 TextView 的实例。

CatAdapter 的构造函数用于把要展示的数据源传递进来,并赋值给一个类变量 cats。

因为 CatAdapter 继承自 RecyclerView.Adapter,所以必须重写以下三个方法:

  • onCreateViewHolder - 创建 ViewHolder 实例,我们把 cat_item 的布局加载进来,创建了一个 ViewHolder 实例。
  • onBindViewHolder - 对 RecyclerView 的子项数据进行赋值,这个方法会在每个子项被滚动到屏幕内时进行。
  • getItemCount - 返回 RecyclerView 的子项总数。

在活动类中使用 RecyclerView :

public class MainActivity extends AppCompatActivity {

    private List<Cat> cats = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();

        RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycler_view);
        LinearLayoutManager layoutManager=new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        CatAdapter adapter=new CatAdapter(cats);
        recyclerView.setAdapter(adapter);
    }

    /**
     * 初始化数据
     */
    private void init() {
        cats.add(new Cat("猫1", R.drawable.cat1));
        cats.add(new Cat("猫2", R.drawable.cat2));
        cats.add(new Cat("猫3", R.drawable.cat3));
        cats.add(new Cat("猫4", R.drawable.cat4));
        cats.add(new Cat("猫5", R.drawable.cat5));
        cats.add(new Cat("猫6", R.drawable.cat6));
        cats.add(new Cat("猫7", R.drawable.cat7));
        cats.add(new Cat("猫8", R.drawable.cat8));
        cats.add(new Cat("猫9", R.drawable.cat9));
    }

}

这里创建了 LinearLayoutManager 的线性布局对象,传递给了 recyclerView.setLayoutManager() 方法。

横向滚动

把 cat_item 中的元素变为垂直排列:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp" />
</LinearLayout>

这里还把 LinearLayout 的宽度设为 100dp,即固定的值。用 match_parent ,会让子项就占满了整个屏幕。把 ImageViewTextView 都设置为水平居中,用 android:layout_marginTop,让文字与图片保持了一段距离。

修改活动类的代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
    ...
}

横向排列

ListView 的布局排列是由自身来管理的,所以存在一定的局限性;而 RecyclerView 把布局的工作交给了 LayoutManager,LayoutManager 制定了一系列可扩展的布局排列接口。

瀑布流布局

使用 StaggeredGridLayoutManager 实现瀑布流布局

修改 cat_item 布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_margin="5dp"
    >
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginTop="10dp" />
</LinearLayout>

把 LinearLayout 的宽度改为 wrap_content,这样宽度会根据实际的布局列数自动适配。 还使用 layout_margin 让子项之间留出一定的间距,最后将 TextView 改为居左对齐。

修改活动类的代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    init();

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

    StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);

    recyclerView.setLayoutManager(layoutManager);
    CatAdapter adapter = new CatAdapter(cats);
    recyclerView.setAdapter(adapter);
}

创建了 StaggeredGridLayoutManager 的实例,它的构造函数接受两个参数,第一个参数用于指定布局的列数,第二个参数用于指定布局的排列方向。

点击事件

RecyclerView 没有像 ListView 一样的 setOnItemClickListener() 事件,所以需要自己给子项具体的 View 注册点击事件。

ListView 的 setOnItemClickListener() 注册的是子项的点击事件,但如果想要注册点击的是子项里具体的某个按钮时,使用 ListView 实现起来就比较麻烦。所以 RecyclerView 直接摈弃了子项点击事件的监听器,把所有的点击事件都交给具体的 View 去注册实现。

修改适配器:

static class ViewHolder extends RecyclerView.ViewHolder {
    View catView;
    ImageView image;
    TextView name;

    public ViewHolder(View view) {
        super(view);
        catView = view;
        image = (ImageView) view.findViewById(R.id.image);
        name = (TextView) view.findViewById(R.id.name);
        Log.d(TAG, "ViewHolder: image:" + image);
        Log.d(TAG, "ViewHolder: name:" + name);
    }
}
public CatAdapter(List<Cat> cats) {
    this.cats = cats;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cat_item, parent, false);

    final ViewHolder holder = new ViewHolder(view);
    holder.catView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int position = holder.getAdapterPosition();
            Cat cat = cats.get(position);
            Toast.makeText(v.getContext(), "你点击了 View " + cat.getName(), Toast.LENGTH_SHORT).show();
        }
    });
    holder.image.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int position = holder.getAdapterPosition();
            Log.d(TAG, "onClick: position:" + position);
            Cat cat = cats.get(position);
            Toast.makeText(v.getContext(), "你点击了图片 " + cat.getName(), Toast.LENGTH_SHORT).show();
        }
    });
    return holder;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值