溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

[Android學(xué)習(xí)筆記三] Support v7提供交錯式網(wǎng)格布局開發(fā)示例

發(fā)布時間:2020-07-09 03:24:22 來源:網(wǎng)絡(luò) 閱讀:1980 作者:secondriver 欄目:移動開發(fā)

   

   本文主要介紹Android Support v7提供的RecycleView和交錯式布局(通常成為瀑布流布局)的使用和事件監(jiān)聽處理。


  1. 涉及到開源庫有:

   Fresco : 

   Facebook開源的不是一般強大的圖片加載組件庫 

   Bufferknife : 

   Android View和事件綁定庫,通過注解完成,在編譯時APT處理注解文檔。

  

  2. 模塊配置

    

   Android Studio模塊,build.gradle配置:

   

apply plugin: 'com.android.application'
android {
    compileSdkVersion 21
    buildToolsVersion '21.1.2'

    defaultConfig {
        applicationId 'secondriver.sdk'
        minSdkVersion 16
        targetSdkVersion 21
        versionCode 1
        versionName '1.0'
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    packagingOptions {
        exclude 'META-INF/services/javax.annotation.processing.Processor'
    }

    lintOptions {
        disable 'InvalidPackage'
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.android.support:recyclerview-v7:21.0.3@aar'
    compile 'com.android.support:cardview-v7:21.0.3@aar'

    compile 'com.facebook.fresco:fresco:0.8.0'
    compile 'com.jakewharton:butterknife:7.0.1'

    testCompile 'junit:junit:4.12'
}


   3. 布局文件


    主布局文件:activity_recycleview.xml 包含一個RecycleView,將作為主屏幕組件。

   

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/swipe_refresh_layout"
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:scrollbars="vertical"
        />
</RelativeLayout>


    RecycleView 通過設(shè)置不同的布局管理器對象來實現(xiàn)不同的布局顯示,如:   

    android.support.v7.widget.LinearLayoutManager 可以實現(xiàn)ListView的布局效果

    android.support.v7.widget.GridLayoutManager  可以實現(xiàn)GridView的布局效果

    android.support.v7.widget.StaggeredGridLayoutManager 可以實現(xiàn)交錯式網(wǎng)格布局效果


    次布局文件(RecycleView中顯示的每一項視圖的布局):item_recycelview.xml 通過com.android.support:CardView包提供的CardView幀式容器布局包含一個ImageView和TextView作為RecycleView的每一項視圖的布局。

    

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:card_view="http://schemas.android.com/apk/res-auto"
              xmlns:fresco="http://schemas.android.com/tools"
              android:layout_width="match_parent" android:layout_height="match_parent"
              android:gravity="center">

    <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        card_view:cardCornerRadius="4dp"
        card_view:cardUseCompatPadding="true">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" android:orientation="vertical">

            <com.facebook.drawee.view.SimpleDraweeView
                android:id="@+id/info_p_w_picpath"
                android:layout_width="300dp"
                android:layout_height="420dp"
                fresco:actualImageScaleType="centerCrop"
                fresco:placeholderImage="@mipmap/ic_launcher"
                fresco:roundAsCircle="false"
                fresco:roundBottomLeft="true"
                fresco:roundBottomRight="true"
                fresco:roundTopLeft="true"
                fresco:roundTopRight="true"
                fresco:roundedCornerRadius="1dp"
                fresco:roundingBorderWidth="2dp"
                />
            <TextView
                android:id="@+id/info_text"
                android:layout_width="200dp"
                android:layout_height="80dp"
                android:textSize="20sp"
                android:textColor="@android:color/holo_blue_dark"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:layout_alignLeft="@id/info_p_w_picpath"
                android:layout_alignRight="@id/info_p_w_picpath"
                android:layout_below="@id/info_p_w_picpath"
                android:gravity="left|center_vertical"/>
        </RelativeLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>

    

    ImageView組件使用的是Fresco庫提供的視圖組件。


 4. Activity實現(xiàn)和數(shù)據(jù)填充


    4.1 RecycleView中的每一項視圖的數(shù)據(jù)組成

       文本信息+ 圖片地址(url,file,resId) 本示例中采用Url網(wǎng)絡(luò)圖片

       

/**
     * View項的數(shù)據(jù)對象
     */
    static class Pair {
        public String text;
        public String url;

        public Pair(String text, String url) {
            this.text = text;
            this.url = url;
        }
    }

        

   

    4.2 RecycleView中國的每一項視圖的數(shù)據(jù)填充,即適配器

        自定義適配器需要實現(xiàn)RecycleView.Adapter類。

  

static class RecycleViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

        /**
         * RecycleView的View項單擊事件監(jiān)聽
         */
        public interface OnRecycleViewItemClickListener {

            void onRecycleViewItemClick(View view, int position);
        }

        private ArrayList<Pair> items = new ArrayList<>();

        private OnRecycleViewItemClickListener mOnRecycleViewItemClickListener;

        public RecycleViewAdapter(ArrayList<Pair> items) {
            this.items = items;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recyclerview, parent, false);
            return new RecycleViewItemHolder(view, mOnRecycleViewItemClickListener);
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            Pair pair = items.get(position);
            ((RecycleViewItemHolder) holder).setContent(pair);
        }

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

        public void setOnRecycleViewItemClickListener(OnRecycleViewItemClickListener onItemClickListener) {
            if (null != onItemClickListener) {
                this.mOnRecycleViewItemClickListener = onItemClickListener;
            }
        }
    }


   主要實現(xiàn)onCreateViewHolder和onBindViewHolder方法。由于RecycleView并未提供為視圖項添加監(jiān)聽事件,這里自定義個一個事件監(jiān)聽接口,在實例化適配器的時候可以選擇設(shè)置事件監(jiān)聽。


   4.3 創(chuàng)建ViewHolder需要通過自定義ViewHolder類繼承RecycleView.ViewHolder。

  

static class RecycleViewItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        @Bind(R.id.info_text)
        public TextView infoTextView;

        @Bind(R.id.info_p_w_picpath)
        public SimpleDraweeView draweeView;

        private RecycleViewAdapter.OnRecycleViewItemClickListener onItemClickListener;

        public RecycleViewItemHolder(View itemView, RecycleViewAdapter.OnRecycleViewItemClickListener onItemClickListener) {
            super(itemView);
            ButterKnife.bind(this, itemView);
            this.onItemClickListener = onItemClickListener;
            itemView.setOnClickListener(this);
        }

        public void setContent(Pair pair) {
            infoTextView.setText(pair.text);
            draweeView.setImageURI(Uri.parse(pair.url));
        }

        @Override
        public void onClick(View v) {
            if (null != onItemClickListener) {
                onItemClickListener.onRecycleViewItemClick(v, getPosition());
            }
        }
    }


    在構(gòu)造方法中的傳入OnRecycleViewItemClickListener對象,并且自定義ViewHolder實現(xiàn)OnClickListener接口,通過為itemView對象設(shè)置OnClickListener監(jiān)聽事件,在onClick方法中將點擊事件的處理交由OnRecycleViewItemClickListener對象處理,從而達到為RecycleView中的itemView注冊點擊事件。


    如果不采用這種方式添加事件監(jiān)聽,就不需要自定義監(jiān)聽接口和自定義ViewHolder實現(xiàn)事件監(jiān)聽接口以及事件處理。另外可以通過獲得的itemView之后,通過組件I的獲取組件來添加事件監(jiān)聽。還可以通過獲得的自定義ViewHolder,來訪問每個組件。


   4.4 Activity的具體實現(xiàn)

    

package secondriver.sdk.activity;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.facebook.drawee.view.SimpleDraweeView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

import butterknife.Bind;
import butterknife.ButterKnife;
import secondriver.sdk.R;

/**
 * Author : secondriver
 * Created : 2015/11/18
 */
public class RecycleViewActivity extends Activity {

    private static final String TAG = RecyclerView.class.getName();

    private static final String[] RES_URL = new String[]{
            "http://p1.wmpic.me/article/2015/11/16/1447644849_hySANEEF.jpg",
            //減少篇幅,此處省去14個圖片Url
    };

    @Bind(R.id.recycler_view)
    public RecyclerView mRecycleView;

    private final int PRE_SCREEN_NUMBER = 6;
    private final int SPAN_COUNT = 2;

    private int previousLastIndex = 0;
    private boolean isSlidingToLast = false;

    private RecycleViewAdapter mAdapter;
    private ArrayList<Pair> mItem = new ArrayList<>();

    //交錯式網(wǎng)格布局管理對象,即通常稱的瀑布流布局
    private StaggeredGridLayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recyclerview);
        ButterKnife.bind(this);
	Fresco.initialize(this); //重要,F(xiàn)resco做一系列初始化工作
        initRecycleView();
    }

    private void initRecycleView() {

        mLayoutManager = new StaggeredGridLayoutManager(SPAN_COUNT, StaggeredGridLayoutManager.VERTICAL);
        mRecycleView.setLayoutManager(mLayoutManager);

        mAdapter = new RecycleViewAdapter(mItem);
        loadData(false);

        mRecycleView.setAdapter(mAdapter);
        mRecycleView.setItemAnimator(new DefaultItemAnimator());

        //RecycleView的View項單擊事件監(jiān)聽
        mAdapter.setOnRecycleViewItemClickListener(new RecycleViewAdapter.OnRecycleViewItemClickListener() {

            @Override
            public void onRecycleViewItemClick(View view, int position) {

                long id = mRecycleView.getChildItemId(view);
                Log.d(TAG, "View項的根視圖:" + view.getClass().getName() + ",position=" + position + " ViewHolder_Id=" + id);

                //通過findViewById查找View項中的元素
                SimpleDraweeView draweeView = (SimpleDraweeView) view.findViewById(R.id.info_p_w_picpath);
                if (null != draweeView) {
                    draweeView.setImageURI(Uri.parse(RES_URL[0]));
                    Toast.makeText(RecycleViewActivity.this, "通過findViewById查找View項中的元素", Toast.LENGTH_LONG).show();
                }

                RecycleViewItemHolder recycleViewItemHolder = (RecycleViewItemHolder) mRecycleView.findViewHolderForPosition(position);
                if (null != recycleViewItemHolder) {
                    recycleViewItemHolder.infoTextView.setText("通過ViewHolder找到View項中的元素");
                }
            }
        });

        //下拉刷新,追加內(nèi)容
        mRecycleView.setOnScrollListener(
                new RecyclerView.OnScrollListener() {

                    @Override
                    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                        super.onScrollStateChanged(recyclerView, newState);

                        if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                            if (isPullToBottom() && isSlidingToLast) {
                                if (mItem.size() > 36) { //最大數(shù)據(jù)量
                                    Toast.makeText(RecycleViewActivity.this, "沒有數(shù)據(jù)了", Toast.LENGTH_LONG).show();
                                    return;
                                } else {
                                    loadData(false);
                                    Log.d(TAG, "notifyItemRangeInserted startPosition=" + previousLastIndex);
                                    mAdapter.notifyItemRangeInserted(previousLastIndex, PRE_SCREEN_NUMBER);
                                }
                            }
                        }
                        if (newState == RecyclerView.SCROLL_STATE_SETTLING) {
                            Log.d(TAG, "settling");
                        }
                    }

                    @Override
                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                        super.onScrolled(recyclerView, dx, dy);
                        isSlidingToLast = dy > 0; //上拉,下滑
                        Log.d(TAG, "dx = " + dx + " dy=" + dy + " isSlidingToLast=" + isSlidingToLast);
                    }
                }
        );

    }

    private boolean isPullToBottom() {
        int[] lastIndexs = mLayoutManager.findLastCompletelyVisibleItemPositions(null);
        Log.d(TAG, "last item =" + Arrays.toString(lastIndexs) + ", have item=" + mAdapter.getItemCount());
        int maxIndex = mAdapter.getItemCount() - 1;
        for (int i : lastIndexs) {
            if (i == maxIndex) {
                return true;
            }
        }
        return false;
    }


    private void loadData(boolean isClear) {
        if (isClear) {
            mItem.clear();
        }
        previousLastIndex = mItem.size();
        Random r = new Random();
        for (int index = 0; index < PRE_SCREEN_NUMBER && index < RES_URL.length; index++) {
            mItem.add(new Pair("Card " + (previousLastIndex + index), RES_URL[r.nextInt(RES_URL.length)]));
        }
        Log.d(TAG, "mItem count =" + mItem.size());
    }
}


    說明:

    RecycleView的ItemView的數(shù)據(jù)由Pair對象管理存儲

    Fresco庫默認(rèn)配置下的使用之前需要初始化調(diào)用Fresco.initialize(Context)

    上述實現(xiàn)了2個事件監(jiān)聽,一個OnScrollerListener由RecycleView提供,實現(xiàn)下拉刷新;一個OnRecycleViewItemClickListener由自定義的RecycleViewAdpater提供,實現(xiàn)單擊itemView來更換圖片(SimpleDraweeView)和文字(TextView)。

    Butterknife和Fresco庫的具體使用參見其Github上的文檔。

 

5. 效果圖

  

  比較遺憾ScreenRecord不支持模擬器和Android4.4一下的系統(tǒng),只能附上截圖。

  

[Android學(xué)習(xí)筆記三] Support v7提供交錯式網(wǎng)格布局開發(fā)示例[Android學(xué)習(xí)筆記三] Support v7提供交錯式網(wǎng)格布局開發(fā)示例

[Android學(xué)習(xí)筆記三] Support v7提供交錯式網(wǎng)格布局開發(fā)示例[Android學(xué)習(xí)筆記三] Support v7提供交錯式網(wǎng)格布局開發(fā)示例


向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI