RecyclerView控件实现横向滚动和瀑布流布局,以及RecyclerView的点击监听(项目已上传GitHub)
先附上我的GitHub項目地址:
https://github.com/Skymqq/RecyclerViewTest.git
?
我們已經知道,ListView的拓展性不好,它只能實現縱向的滾動的效果,如果想進行橫向滾動的效果,ListView就做不到了,毫無疑問,RecyclerView是可以做到的。
fruit_item.xml列表項布局文件代碼:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="100dp"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_name"android:layout_width="40dp"android:layout_height="40dp"android:layout_gravity="center_horizontal" /><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="10dp" /></LinearLayout>可以看到,我們將LinearLayout改成垂直方向排列,并且把寬度設置為100dp。這里將寬度指定為固定值是因為每種水果的文字長度不一致,如果用wrap_content,RecyclerView的子項就會有長有短,非常不美觀;而如果使用match_parent,就會導致寬度過長,一個子項占滿了整個屏幕。
然后將ImageView和TextView都設置成了在布局中水平居中,并且使用layout_marginTop屬性讓文字和圖片之間保持一些距離。
MainActivity.java代碼:
package com.example.administrator.activitydemo;import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView;import java.util.ArrayList; import java.util.List;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;private String[] data = {"Apple", "Banana", "Orange", "Watermelon","Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango","Apple", "Banana", "Orange", "Watermelon","Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango"};private int[] res = {R.drawable.apple, R.drawable.banana, R.drawable.orange, R.drawable.watermelon,R.drawable.pear, R.drawable.grape, R.drawable.pineapple, R.drawable.strawberry, R.drawable.cherry, R.drawable.mango,R.drawable.apple, R.drawable.banana, R.drawable.orange, R.drawable.watermelon,R.drawable.pear, R.drawable.grape, R.drawable.pineapple, R.drawable.strawberry, R.drawable.cherry, R.drawable.mango};private List<Fruit> fruitList;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();//初始化UI控件initData();//初始化數據}private void initView() {recyclerView = (RecyclerView) findViewById(R.id.recyclerView);}private void initData() {initFruits();//初始化水果數據LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);//實例化布局管理器layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);//為布局管理器設定線性方向recyclerView.setLayoutManager(layoutManager);//為RecyclerView控件設置布局管理器FruitAdapter adapter = new FruitAdapter(fruitList);//實例化適配器recyclerView.setAdapter(adapter);//為RecyclerView控件設置適配器}private void initFruits() {fruitList = new ArrayList<>();for (int i = 0; i < data.length; i++) {Fruit fruit = new Fruit(data[i], res[i]);fruitList.add(fruit);}}}效果圖:
MainActivity.java中加入了一行代碼,調用LinearLayoutManager的setOrientation()方法來設置布局的排列方向,默認是縱向排列的,我們傳入的LinearLayoutManager.HORIZONTAL表示讓布局橫行排列,這樣RecyclerView就可以橫向滾動了。
為什么ListView很難或者根本無法實現的效果在RecyclerView上這么輕松就能實現了呢?
這主要得益于RecyclerView出色的設計。ListView的布局排列是由自身去管理的,而RecyclerView則將這個工作交給了LayoutManager,LayoutManager中制定了一套可拓展的布局排列接口,子類只要按照接口的規范來實現,就能定制出各種不同排列方式的布局了。
除了LinearLayoutManager之外,RecyclerView還給我們提供了GridLayoutManager和StaggeredGridLayoutManager這兩種內置的布局排列方式。GridLayoutManager可以用于實現網絡布局,StaggeredGridLayoutManager可以用于實現瀑布流布局。這里我們來實現一下效果更加酷炫的瀑布流布局。
fruit_item.xml代碼:
<?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:layout_margin="5dp"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_name"android:layout_width="40dp"android:layout_height="40dp"android:layout_gravity="center_horizontal" /><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="left"android:layout_marginTop="10dp" /></LinearLayout>這里做了幾處小的調整,首先將LinearLayout的寬度由100dp改成了match_parent,因為瀑布流布局的寬度應該是根據布局的列數來自動適配的,而不是一個固定值。另外我們使用了layout_margin屬性來讓子項之間互留一點間距,這樣就不至于所有子項都緊貼在一起。還有就是將TextView的對其屬性改成了居左對齊,因為待會我們會將文字的長度變長,如果還是居中就會很怪。
MainActivity.java代碼:
package com.example.administrator.activitydemo;import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager;import java.util.ArrayList; import java.util.List; import java.util.Random;public class MainActivity extends AppCompatActivity {private RecyclerView recyclerView;private String[] data = {"Apple", "Banana", "Orange", "Watermelon","Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango","Apple", "Banana", "Orange", "Watermelon","Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango"};private int[] res = {R.drawable.apple, R.drawable.banana, R.drawable.orange, R.drawable.watermelon,R.drawable.pear, R.drawable.grape, R.drawable.pineapple, R.drawable.strawberry, R.drawable.cherry, R.drawable.mango,R.drawable.apple, R.drawable.banana, R.drawable.orange, R.drawable.watermelon,R.drawable.pear, R.drawable.grape, R.drawable.pineapple, R.drawable.strawberry, R.drawable.cherry, R.drawable.mango};private List<Fruit> fruitList;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();//初始化UI控件initData();//初始化數據}private void initView() {recyclerView = (RecyclerView) findViewById(R.id.recyclerView);}private void initData() {initFruits();//初始化水果數據StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);//3列,垂直recyclerView.setLayoutManager(layoutManager);//為RecyclerView控件設置布局管理器FruitAdapter adapter = new FruitAdapter(fruitList);//實例化適配器recyclerView.setAdapter(adapter);//為RecyclerView控件設置適配器}private void initFruits() {fruitList = new ArrayList<>();for (int i = 0; i < data.length; i++) {Fruit fruit = new Fruit(getRandomLengthName(data[i]), res[i]);fruitList.add(fruit);}}private String getRandomLengthName(String name) {Random random = new Random();int length = random.nextInt(20) + 1;//取0~20之間的一個隨機數StringBuilder builder = new StringBuilder();for (int i = 0; i < length; i++) {builder.append(name);//字符串拼接}return builder.toString();}}效果圖:
這里的水果的名字長短都是隨機生成的,所以當我們再次運行一次程序,效果圖又會不一樣的。
?
RecyclerView的點擊事件:
和ListView一樣,RecyclerView也必須要能響應點擊事件才可以,不然的話就沒什么實際用途了。不過不同于ListView的是,RecyclerView并沒有提供類似于setOnClickListener()這樣的注冊監聽方法,而是需要我們自己給子項具體的View去注冊點擊事件,相比于ListView來說,實現起來要復雜一些。
那么你可能就有疑問了,為什么RecyclerView在各個方面的設計都要優于ListView,偏偏在點擊事件上卻沒有處理得非常好呢?其實不是這樣的,ListView在點擊事件上的處理并不人性化,setOnClickListener()方法注冊的是子項的點擊事件,但如果我想點擊的是子項里具體的某一個按鈕呢?雖然ListView也是能夠做到的,但是實現起來就比較麻煩了。為此,RecyclerView干脆直接摒棄了子項點擊事件的監聽器,所有的點擊事件都由具體的View去注冊,就再沒有這個困擾了。
下面我們來具體學習一下如何在RecyclerView中注冊點擊事件,修改FruitAdapter中的代碼,如下所示:
package com.example.administrator.activitydemo;import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast;import java.util.List;public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {private List<Fruit> fruitList;public FruitAdapter(List<Fruit> fruitList) {this.fruitList = fruitList;}@NonNull@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.fruit_item, viewGroup, false);final ViewHolder viewHolder = new ViewHolder(view);viewHolder.iv_name.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int position = viewHolder.getAdapterPosition();Fruit fruit = fruitList.get(position);Toast.makeText(v.getContext(), "you clicked ImageView: " + fruit.getName(), Toast.LENGTH_SHORT).show();}});viewHolder.tv_name.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int position = viewHolder.getAdapterPosition();Fruit fruit = fruitList.get(position);Toast.makeText(v.getContext(), "you clicked TextView: " + fruit.getName(), Toast.LENGTH_SHORT).show();}});return viewHolder;}@Overridepublic void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {Fruit fruit = fruitList.get(i);viewHolder.iv_name.setImageResource(fruit.getImageId());viewHolder.tv_name.setText("" + fruit.getName());}@Overridepublic int getItemCount() {return fruitList.size();}static class ViewHolder extends RecyclerView.ViewHolder {View fruitView;ImageView iv_name;TextView tv_name;public ViewHolder(@NonNull View itemView) {super(itemView);fruitView = itemView;iv_name = (ImageView) itemView.findViewById(R.id.iv_name);tv_name = (TextView) itemView.findViewById(R.id.tv_name);}}}我們先是修改了內部類ViewHolder,在這個內部類中聲名了一個View類的變量fruitView,并且在其構造函數里面為fruitView初始化了,其次我們在onCreateView()函數中通過獲得的View實例來獲得我們點擊屏幕適配器當前的位置,然后根據適配器的位置,在List列表中找到對應的Fruit實例,最后通過Fruit實例獲得水果的名稱。最終,分別為ImageView和TextView設置點擊監聽,Toast提示出水果的名稱,這樣也可以根據Toast提示,很清晰地分辨我們點擊的是文字還是圖片。
點擊圖片后的效果圖:
點擊文字后的效果圖:
?
?
?
總結
以上是生活随笔為你收集整理的RecyclerView控件实现横向滚动和瀑布流布局,以及RecyclerView的点击监听(项目已上传GitHub)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 按什么计算个人所得税
- 下一篇: 人生意外险是什么