Android5.x 新控件之RecyclerView,CardView,Palette的使用

pdce 9年前發布 | 254K 次閱讀 Android Android開發 移動開發

自Android5.0發布以來,谷歌推出全新的Material Desigen設計風格,時過一年多了,在國內也看到很多應用在慢

慢適應MD設計風格。其中比較好的app就是網易新聞客戶端了,其設計風格基本符合MD要求。鑒于越來多App采

用MD設計風格,作為吊絲程序員的我們怎能落后呢?那就讓我們來學習一些Android5.x新推出的一些控件吧。

先上效果圖:
這里寫圖片描述

注明:我的開發環境是AS1.0 ,使用Eclipse的童鞋自行配置。為了能使用Android5.0的一些新控件,我們不

得不引用Support v7包,在AS里很好配置,直接在build.gradle文件下添加如下配置:

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:recyclerview-v7:21.0.3'
    compile 'com.android.support:cardview-v7:21.0.3'
    compile 'com.android.support:palette-v7:22.2.0'
}

RecyclerView控件

類似ListView ,GridView,RecyclerView也是一個繼承ViewGroup的容器控件,用于在有限的界面視圖情況下裝

載更多的內容。我們通過代碼來看看RecyclerView控件怎么使用的吧!先XML從布局看

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

很簡單,直接引用Support v7包里的RecyclerView就可以了,貌似布局文件里沒有太多的配置,不像ListView和

GridView控件有很多配置比如:android:dividerHeight ,android:divider,android:numColumns等。這是因

為RecyclerView雖然也是容器控件,大多數的效果顯示可以通過代碼來控制顯示,但是RecyclerView更加自由,

更加包容,用戶更容易去定義它的內容顯示方

式。接下來通過代碼看怎么使用RecyclerView吧!

private void initViews() {
        recylerView = findView(R.id.recyclerview);
        //設置布局顯示方式
        recylerView.setLayoutManager(new LinearLayoutManager(this, LinearLayout.VERTICAL, true));
        //設置添加刪除item時候的動畫
        recylerView.setItemAnimator(new DefaultItemAnimator());
    }

是不是感覺還是蠻簡單的嘛?就兩行代碼,我們來看看setLayoutManager設置布局顯示方式方法吧!

setLayoutManager()方法接受一個 LayoutManager 布局管理參數。參數類型可以有以下幾種:

  1. LinearLayoutManager:線性布局
  2. GridLayoutManager:網格布局
  3. StaggeredGridLayoutManager:流式布局
  4. </ol>

    那么怎么new一個LayoutManager出來呢?舉個例子:

    new LinearLayoutManager(this, LinearLayout.VERTICAL, true)

    第一個參數 Context ,第二個參數:布局方向LinearLayout.VERTICAL垂直和LinearLayout.HORIZONTAL水平,

    第三個參數:表示是否從最后的Item數據開始顯示,ture表示是,false就是正常顯示—從開頭顯示。

    setItemAnimator()方法的作用是設置當前RecyclerView容器有子Item改變時(添加item或者刪除item)導致

    整個布局的動畫效果。一般我們new 一個系統默認的動畫出來就好了。

    RecyclerView適配器

    既然RecyclerView是一個容器控件,那么里面總的裝載內容吧,也就是的有一個自己的適配器。來看看適配器怎么

    實現的吧!

    /**

    • Description:RecyclerView 適配器
    • User: xjp
    • Date: 2015/6/8
    • Time: 10:15 */

    public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {

    private Context context;
    private List<ModelBean> list;
    private Resources res;
    
    public RecyclerAdapter(Context context, List<ModelBean> list) {
        this.context = context;
        this.list = list;
        res = context.getResources();
    }
    
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_card_view, parent, false);
        return new MyViewHolder(view);
    }
    
    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        final ModelBean bean = list.get(position);
        holder.title.setText(bean.getTitle());
        holder.imageView.setImageResource(bean.getResId());
    }
    
    @Override
    public int getItemCount() {
        return null == list ? 0 : list.size();
    }
    
    public class MyViewHolder extends RecyclerView.ViewHolder {
    
        private ImageView imageView;
        private TextView title;
    
        public MyViewHolder(View view) {
            super(view);
            imageView = (ImageView) view.findViewById(R.id.pic);
            title = (TextView) view.findViewById(R.id.name);
        }
    }
    

    }</pre>

    看到嘛?我們是繼承RecyclerView.Adapter類,實現里面的抽象方法即可。可以看到RecyclerView.Adapter適配

    器里面有一套完整的機制來控制之ItemView的查找和顯示。通過內部類MyViewHolder繼承

    RecyclerView.ViewHolder封裝容器中的ItemView,實現onCreateViewHolder抽象方法來加載ItemView的布

    局,實現onBindViewHolder抽象方法來綁定容器中的ItemView,進而進行賦值。

    ItemView點擊事件

    細心的你會發現,很遺憾的是RecyclerView沒有提供setItemOnClickListener點擊監聽方法。那么我們要監聽每個

    ItemView的點擊事件怎么辦呢?沒關系!我們來看看代碼中怎么實現吧!

     @Override
        public void onBindViewHolder(final MyViewHolder holder, final int position) {
            final ModelBean bean = list.get(position);
            holder.title.setText(bean.getTitle());
            holder.imageView.setImageResource(bean.getResId());

    /**

         * 調用接口回調
         */
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != listener)
                    listener.onItemClick(position, bean);
            }
        });
    }
    
    
    

    /**

     * 內部接口回調方法
     */
    public interface OnItemClickListener {
        void onItemClick(int position, Object object);
    }
    
    /**
     * 設置監聽方法
     *
     * @param listener
     */
    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }</pre><br />
    

    在RecyclerView的適配器類中定義了一個OnItemClickListener接口,然后在onBindViewHolder方法中設置每個holder.itemView的點擊事件,外面調用setOnItemClickListener方法即可

    adapter.setOnItemClickListener(new RecyclerAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(int position, Object object) {
                    Toast.makeText(MainActivity.this, ((ModelBean) object).getTitle(), Toast.LENGTH_SHORT).show();
                }
            });

    RecyclerView添加,刪除,更新數據

    和ListView,GridView容器不一樣的是,RecyclerView容器更新數據的方法有很多,不信你看:

    1. notifyDataSetChanged():更新所有數據
    2. notifyItemInserted(int position):在position位置插入數據的時候更新
    3. notifyItemRemoved(int position):移除postion位置的數據的時候更新
    4. notifyItemChanged(int position):當postion位置數據有改變時候更新
    5. notifyItemMoved(int fromPosition, int toPosition):移除從位置formPosition到toPosition位置數據更新
    6. notifyItemRangeChanged(int positionStart, int itemCount)
    7. notifyItemRangeInserted(int positionStart, int itemCount)
    8. notifyItemRangeRemoved(int positionStart, int itemCount)
    9. </ol>

      如果你在代碼里設置了RecyclerView的ItemView改變時有動畫效果的話

      recylerView.setItemAnimator(new DefaultItemAnimator());

      在RecyclerView適配器更新數據的時候就會有系統默認的動畫效果,童鞋們可以根據下面提供的源碼看效果。

      RecyclerView控件使用基本就

      是以上內容,最后我會提供一個RecyclerView,CardView,Palette一起使用的源碼例子,接著往下看吧騷年!

      CardView控件

      CardView稱之為卡片,也是Android5.0推出來的 Support v7包里的widget,CardView是繼承自FrameLayout。

      從XML中看它是怎么使用的

      <android.support.v7.widget.CardView xmlns:android="
      
      
      <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical">
      
          <ImageView
              android:id="@+id/pic"
              android:layout_width="match_parent"
              android:layout_height="0dp"
              android:layout_centerInParent="true"
              android:layout_weight="3"
              android:scaleType="fitXY"
              android:src="@drawable/img1" />
      
          <TextView
              android:id="@+id/name"
              android:layout_width="match_parent"
              android:layout_height="0dp"
              android:layout_weight="1"
              android:clickable="true"
              android:gravity="center"
              android:padding="5dp"
              android:text="圖片描述"
              android:textColor="@android:color/black"
              android:textSize="16sp" />
      </LinearLayout>
      
      

      </android.support.v7.widget.CardView></pre>
      在使用CardView的時候需要引入屬性命名空間,也就是加入以下代碼

      xmlns:card="http://schemas.android.com/apk/res-auto"

      和自定義控件一樣,引入命名空間是為了使用CardView的屬性值,名字“card”可以任意。來看看CardView有哪

      些常用的屬性吧!

      1. cardElevation:卡片陰影的寬度
      2. cardMaxElevation:最大卡片陰影的寬度
      3. cardBackgroundColor:卡片的背景顏色
      4. cardCornerRadius :卡片的圓角半徑
      5. </ol>

        CardView只需要在XML布局文件里配置各種參數,代碼中無需任何操作。其實CardView就是一個FrameLayout容器控件,只是添加了一些屬性而已,使用很簡單,只要掌握以上四種屬性配置即可。

        Palette

        Palette類也是Android5.0引進來的一個獲取Bitmap顏色值的一個類。google為了兼容前面的版本也把這個類放在

        了Support v7 Library包里,需要使用該類可以在項目中引進

        compile 'com.android.support:palette-v7:22.2.0'

        我們從代碼中來看看它是怎么使用的
         //異步獲得bitmap圖片顏色值
                Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
                    @Override
                    public void onGenerated(Palette palette) {
                        Palette.Swatch vibrant = palette.getVibrantSwatch();//有活力

                    if (vibrant != null) {
                        holder.title.setBackgroundColor(
                                vibrant.getRgb());
                        holder.title.setTextColor(
                                vibrant.getTitleTextColor());
                    }
                }
            });</pre><br />
        

        由于在Android設備中,對圖像的處理有可能是耗時操作,因此,Palette類通過異步接口onGenerated回調的方法

        來獲得Bitmap的顏色值。Palette類獲得的顏色值有以下幾種類型:

        1. Palette.Swatch a = palette.getVibrantSwatch();//有活力
        2. Palette.Swatch b = palette.getDarkVibrantSwatch();//有活力 暗色
        3. Palette.Swatch c = palette.getLightVibrantSwatch();//有活力 亮色
        4. Palette.Swatch d = palette.getMutedSwatch();//柔和
        5. Palette.Swatch e = palette.getDarkMutedSwatch();//柔和 暗色
        6. Palette.Swatch f = palette.getLightMutedSwatch();//柔和 亮色
        7. </ol>

          我們從以上顏色中可以獲取到如下顏色值:

          1. int color1 = a.getBodyTextColor();//內容顏色
          2. int color2 = a.getTitleTextColor();//標題顏色
          3. int color3 = a.getRgb();//rgb顏色
          4. </ol>

            綜合例子

            通過以上的了解,這里提供一個綜合的例子來看看RecyclerView,CardView,Palette結合的使用。以后給出

            MainActivity和Adapter的實現

            package com.xjp.androidmddemo.activity;

            import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast;

            import com.xjp.androidmddemo.R; import com.xjp.androidmddemo.activity.adapter.RecyclerAdapter; import com.xjp.androidmddemo.activity.model.ModelBean;

            import java.util.ArrayList; import java.util.List;

            public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener, View.OnClickListener {

            protected Toolbar toolbar;
            protected TextView title;
            protected Spinner spinner;
            protected Button add;
            
            private RecyclerView recylerView;
            private List<ModelBean> beanList;
            private RecyclerAdapter adapter;
            private String des[] = {"云層里的陽光", "好美的海灘", "好美的海灘", "夕陽西下的美景", "夕陽西下的美景"
                    , "夕陽西下的美景", "夕陽西下的美景", "夕陽西下的美景", "好美的海灘"};
            
            private int resId[] = {R.drawable.img1, R.drawable.img2, R.drawable.img2, R.drawable.img3,
                    R.drawable.img4, R.drawable.img5, R.drawable.img3, R.drawable.img1};
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                initViews();
                initData();
                initSpinner();
            }
            
            
            private void initSpinner() {
                String categorys[] = this.getResources().getStringArray(R.array.categorys);
                ArrayAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, categorys);
            
                // 為adapter設置下拉菜單樣式
                adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            
                // spinner設置adapter
                spinner.setAdapter(adapter);
                spinner.setOnItemSelectedListener(this);
            }
            
            
            private void initViews() {
            
                toolbar = findView(R.id.toolbar);
                if (null != toolbar) {
                    setSupportActionBar(toolbar);
                    title = findView(R.id.toolbar_title);
                    spinner = findView(R.id.toolbar_category);
                    add = findView(R.id.button_add);
                    if (null != title) {
                        title.setText(getTitle());
                    }
                }
            
                add.setOnClickListener(this);
            
                recylerView = findView(R.id.recyclerview);
                //設置布局顯示方式
                recylerView.setLayoutManager(new LinearLayoutManager(this, LinearLayout.VERTICAL, true));
                //設置添加刪除item時候的動畫
                recylerView.setItemAnimator(new DefaultItemAnimator());
            }
            
            private void initData() {
                beanList = new ArrayList<>();
                for (int i = 0; i < 8; i++) {
                    ModelBean bean = new ModelBean();
                    bean.setResId(resId[i]);
                    bean.setTitle(des[i]);
                    beanList.add(bean);
                }
                adapter = new RecyclerAdapter(this, beanList);
                recylerView.setAdapter(adapter);
                adapter.setOnItemClickListener(new RecyclerAdapter.OnItemClickListener() {
                    @Override
                    public void onItemClick(int position, Object object) {
                        Toast.makeText(MainActivity.this, ((ModelBean) object).getTitle(), Toast.LENGTH_SHORT).show();
                    }
                });
            }
            
            
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                switch (position) {
                    case 0:
                        recylerView.setLayoutManager(new LinearLayoutManager(this, LinearLayout.VERTICAL, true));
                        break;
                    case 1:
                        recylerView.setLayoutManager(new LinearLayoutManager(this, LinearLayout.HORIZONTAL, true));
                        break;
                    case 2:
                        recylerView.setLayoutManager(new GridLayoutManager(this, 2));
                        break;
                    case 3:
                        recylerView.setLayoutManager(new GridLayoutManager(this, 2, LinearLayout.HORIZONTAL, true));
                        break;
                    case 4:
                        recylerView.setLayoutManager(new StaggeredGridLayoutManager(2, LinearLayout.VERTICAL));
                        break;
                }
            }
            
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            
            }
            
            @Override
            public void onClick(View v) {
                ModelBean bean = new ModelBean();
                bean.setTitle("這是新添加的");
                bean.setResId(R.drawable.img5);
                beanList.add(0, bean);
               // adapter.notifyDataSetChanged();//更新全部數據
               // adapter.notifyItemInserted(0);//在
               // adapter.notifyItemRemoved(0);
               // adapter.notifyItemChanged(0);
               // adapter.notifyItemMoved(0,1);
               // adapter.notifyItemRangeChanged(0,2);
               // adapter.notifyItemRangeInserted(0,2);
               // adapter.notifyItemRangeRemoved(0,2);
            
            }
            
            protected <T extends View> T findView(int id) {
                return (T) findViewById(id);
            }
            

            }

            ............................

            package com.xjp.androidmddemo.activity.adapter;

            import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.support.v7.graphics.Palette; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView;

            import com.xjp.androidmddemo.R; import com.xjp.androidmddemo.activity.model.ModelBean;

            import java.util.List;

            /**

            • Description:RecyclerView 適配器
            • User: xjp
            • Date: 2015/6/8
            • Time: 10:15 */

            public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {

            private Context context;
            private List<ModelBean> list;
            private Resources res;
            private OnItemClickListener listener;
            
            public RecyclerAdapter(Context context, List<ModelBean> list) {
                this.context = context;
                this.list = list;
                res = context.getResources();
            }
            
            
            @Override
            public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                View view = LayoutInflater.from(context).inflate(R.layout.item_card_view, parent, false);
                return new MyViewHolder(view);
            }
            
            @Override
            public void onBindViewHolder(final MyViewHolder holder, final int position) {
            
                final ModelBean bean = list.get(position);
                holder.title.setText(bean.getTitle());
                holder.imageView.setImageResource(bean.getResId());
                Bitmap bitmap = BitmapFactory.decodeResource(res, bean.getResId());
                //異步獲得bitmap圖片顏色值
                Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
                    @Override
                    public void onGenerated(Palette palette) {
                        Palette.Swatch vibrant = palette.getVibrantSwatch();//有活力
                        Palette.Swatch c = palette.getDarkVibrantSwatch();//有活力 暗色
                        Palette.Swatch d = palette.getLightVibrantSwatch();//有活力 亮色
                        Palette.Swatch f = palette.getMutedSwatch();//柔和
                        Palette.Swatch a = palette.getDarkMutedSwatch();//柔和 暗色
                        Palette.Swatch b = palette.getLightMutedSwatch();//柔和 亮色
            
                        if (vibrant != null) {
                            int color1 = vibrant.getBodyTextColor();//內容顏色
                            int color2 = vibrant.getTitleTextColor();//標題顏色
                            int color3 = vibrant.getRgb();//rgb顏色
            
                            holder.title.setBackgroundColor(
                                    vibrant.getRgb());
                            holder.title.setTextColor(
                                    vibrant.getTitleTextColor());
                        }
                    }
                });
            
                /**
                 * 調用接口回調
                 */
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (null != listener)
                            listener.onItemClick(position, bean);
                    }
                });
            }
            
            @Override
            public int getItemCount() {
                return null == list ? 0 : list.size();
            }
            
            
            public class MyViewHolder extends RecyclerView.ViewHolder {
            
                private ImageView imageView;
                private TextView title;
            
                public MyViewHolder(View view) {
                    super(view);
                    imageView = (ImageView) view.findViewById(R.id.pic);
                    title = (TextView) view.findViewById(R.id.name);
                }
            }
            
            /**
             * 內部接口回調方法
             */
            public interface OnItemClickListener {
                void onItemClick(int position, Object object);
            }
            
            /**
             * 設置監聽方法
             *
             * @param listener
             */
            public void setOnItemClickListener(OnItemClickListener listener) {
                this.listener = listener;
            }
            
            

            }</pre>
            源碼地址 Demo源碼例子

            來自:http://blog.csdn.net/feiduclear_up/article/details/46439005

 本文由用戶 pdce 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!