二、Android-UI(RecyclerView)

2.六、滾動控件-RecylerView

ListView雖然使用的效果很好可是也是有缺點的android

不使用一些技巧來提高它的運行效率,性能就很是差app

擴展性也不是很好ide

只能實現數據的縱向滾動效果函數

實現橫向滾動是作不到的佈局

 

Android提供一個更強大的滾動控件---RecylerView性能

是一個加強版的ListViewgradle

不只能夠輕鬆實現和ListView一樣效果優化

還優化了ListView中 存在的不足之處ui

 

目前官方更推薦使用RecyclerViewthis

將來會有更多的程序主鍵從ListView轉向RecyclerView

 

一、基本用法

首先再app/build.gradle文件中引入:

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

 

再first_activity中:

<?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"> <android.support.v7.widget.RecyclerView
        android:id="@+id/recyler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>
       
</LinearLayout>

 

新建一個適配類

繼承RecyclerView.Adapter,而且將泛型指定爲內部類ViewHolder

public class FruitAdaperRecyler extends RecyclerView.Adapter<FruitAdaperRecyler.ViewHolder> {
    private List<Fruit> fruitList;

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,null,false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = fruitList.get(position);
        holder.textView.setText(fruit.getName());
       holder.imageView.setImageResource(fruit.getId());

    }
    @Override
    public int getItemCount() {
        return fruitList.size();
    }

     //自定義的內部類
      class ViewHolder extends RecyclerView.ViewHolder{
        //佈局文件中的兩個控件
        ImageView imageView;
        TextView textView;
        public ViewHolder(View itemView) {
            super(itemView);
            imageView  = (ImageView) itemView.findViewById(R.id.image_view);
            textView = (TextView) itemView.findViewById(R.id.text_view);
        }
    }

    //構造器
    public FruitAdaperRecyler(List<Fruit> fruits){
        this.fruitList = fruits;
    }
}

 

首先定義一個內部類ViewHolder

須要繼承RecyclerHolder

而後再構造參數中要傳入一個view參數

這個參數一般就是RecyclerView子項的最外層佈局

那麼就能夠經過findViewById()方法獲取到佈局中的ImageView和TextView的實例

 

FruitAdaperRecyler類中有一個構造函數就是將要展現的數據傳進來

而且複製給一個全局變量,後續的操做都是在全局變量的基礎上進行的

 

FruitAdaperRecyler繼承RecyclerView.Adapter就須要實現其中的三個方法

一、omCreateViewHolder()方法就是用於建立viewholder的實例,再方法中將fruit_item佈局加載進來

  而後建立一個viewHolder實例,並把加載出來的佈局傳入傳入到構造函數中

  最後將viewHolder的實例返回

二、onBinbViewHolder()方法用於對Recycler子項的數據進行賦值,會在每個子項被滾動到屏幕內時執行

  這裏經過position參數能夠得到到當前的Fruit的實例,而後進行設置id和name

三、getItemCount()就是返回REcyclerView一共有多少個子項,直接返回數據源的長度便可

 

mainAcctivity中的代碼:

public class MainActivity extends AppCompatActivity {
    private List<Fruit> fruitList = new ArrayList<>();

    private void initFruit(){
            Fruit apple = new Fruit("Apple1",R.drawable.qq);
            fruitList.add(apple);
            Fruit apple1 = new Fruit("Apple2",R.drawable.qq);
            fruitList.add(apple1);
            Fruit apple2 = new Fruit("Apple3",R.drawable.qq);
            fruitList.add(apple2);
            Fruit apple3 = new Fruit("Apple4",R.drawable.qq);
            fruitList.add(apple3);
            Fruit apple4 = new Fruit("Apple5",R.drawable.qq);
            fruitList.add(apple4);
            Fruit apple5 = new Fruit("Apple6",R.drawable.qq);
            fruitList.add(apple5);
            Fruit apple6 = new Fruit("Apple7",R.drawable.qq);
            fruitList.add(apple6);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.firstlayout);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null){
            actionBar.hide();
        }
        //初始化
        initFruit();

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyler_view); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(linearLayoutManager); FruitAdaperRecyler fruitAdaperRecyler = new FruitAdaperRecyler(fruitList); recyclerView.setAdapter(fruitAdaperRecyler);
    }
}

使用initFruit進行初始化數據

再onCreate()方法中首先獲取RecyclerView的實例

而後建立一個LinearLayoutManager對象,在這裏是線性佈局的意思

再進行建立FruitAdapterRecyler的實例

而且將水果的數據傳入

醉胡調用RecyclerView的setAdapter()方法來完成適配器的設置

此時RecyrView和數據之間的關聯創建完成

實現了和ListView幾乎同樣的效果

再實現的過程當中邏輯清晰

 

二、實現橫向滾動和瀑布流佈局

文件中的佈局元素都是水平排列的

適用於縱向滾動的場景

 

 實現橫向滾動則須要改爲垂直排列

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="100dp"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"

        />
    <TextView
        android:id="@+id/text_view"
        android:layout_marginTop="10dp"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

 

將LinerLayout改爲垂直方向的排列

此時設置的寬度時100dp

將寬度指定爲固定的值能夠有效的包裹文字,防止其過長或者太短的美觀問題

 

進行修改代碼:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.firstlayout);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null){
            actionBar.hide();
        }
        //初始化
        initFruit();

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

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
  linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

        recyclerView.setLayoutManager(linearLayoutManager);
        FruitAdaperRecyler fruitAdaperRecyler = new FruitAdaperRecyler(fruitList);

        recyclerView.setAdapter(fruitAdaperRecyler);
    }

 

 之加入了一行代碼

調用LinearLayoutManager的setOrientation()方法來設置不久排列的排列方向

此時的設置表示橫向排列

默認是縱向排列

 

 

 處LInearLayoutManager以外

還提供了GridLayoutManagerStaggeredGridLayoutManager這兩種內置的佈局排列方式

前者能夠實現網格佈局

後者能夠實現瀑布流佈局

 

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp">

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"

        />
    <TextView
        android:id="@+id/text_view"
        android:layout_marginTop="10dp"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.firstlayout);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null){
            actionBar.hide();
        }
        //初始化
        initFruit();

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyler_view);
 StaggeredGridLayoutManager staggeredGridLayoutManager =  new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(staggeredGridLayoutManager);
        FruitAdaperRecyler fruitAdaperRecyler = new FruitAdaperRecyler(fruitList);
        recyclerView.setAdapter(fruitAdaperRecyler);
    }
StaggeredGridLayoutManager staggeredGridLayoutManager =  new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); 

第一個參數用於指定列數

第二個參數用於指定佈局的排列方向

 

 

 

 結果展現:

 

三、點擊事件:

全部的點擊事件都有具體的View去註冊

代碼以下: 

public class FruitAdaperRecyler extends RecyclerView.Adapter<FruitAdaperRecyler.ViewHolder> { private List<Fruit> fruitList; @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,null,false); final ViewHolder viewHolder = new ViewHolder(view); //點擊事件的監聽 viewHolder.fruitView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = viewHolder.getAdapterPosition(); Fruit fruit = fruitList.get(position); Toast.makeText(v.getContext(),"clicked:"+fruit.getName(),Toast.LENGTH_LONG).show(); } }); viewHolder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = viewHolder.getAdapterPosition(); Fruit fruit = fruitList.get(position); Toast.makeText(v.getContext(),"click image :" + fruit.getName(),Toast.LENGTH_LONG).show(); } }); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { Fruit fruit = fruitList.get(position); holder.textView.setText(fruit.getName()); holder.imageView.setImageResource(fruit.getId()); } @Override public int getItemCount() { return fruitList.size(); } //自定義的內部類
      class ViewHolder extends RecyclerView.ViewHolder{ //佈局文件中的兩個控件
 ImageView imageView; TextView textView;  View fruitView; public ViewHolder(View itemView) { super(itemView);  fruitView=itemView; imageView = (ImageView) itemView.findViewById(R.id.image_view); textView = (TextView) itemView.findViewById(R.id.text_view); } } //構造器
    public FruitAdaperRecyler(List<Fruit> fruits){ this.fruitList = fruits; } }

 

首先是在ViewHolder中添加了fruitView變量來保存子項最外層的佈局實例

而後再onCreateViewHolder()方法中註冊點擊事件

首先是獲取用戶點擊的position

而後經過position獲取用戶拿到享用的Fruit實例

最後將內容進行顯示

點擊文字和圖片均可以正常的進行打印顯示的信息

相關文章
相關標籤/搜索