RecyclerView學(xué)習(xí)筆記(基礎(chǔ)篇)

RecyclerView學(xué)習(xí)筆記

一钝域、RecyclerView的定義

在以前的開(kāi)發(fā)中,我們經(jīng)常使用ListView來(lái)實(shí)現(xiàn)列表的功能∨呶現(xiàn)在Google為我們提供了一個(gè)更強(qiáng)大的滾動(dòng)控件RecyclerView拘领,他不僅可以實(shí)現(xiàn)ListView的功能褐墅,還優(yōu)化了ListView的效率問(wèn)題痴颊。RecyclerView還支持橫向滾動(dòng)和瀑布流赏迟,所以現(xiàn)在Google官方更加推薦使用RecyclerView進(jìn)行開(kāi)發(fā)。

二蠢棱、RecyclerView的用法

  1. 打開(kāi)Android Studio的project structrue設(shè)置锌杀,在dependencies的閉包中導(dǎo)入RecyclerView的依賴庫(kù)。


    image.png
  2. 在布局文件中添加以下代碼加入RecyclerView控件

<?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/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

  1. 創(chuàng)建數(shù)據(jù)源Sport
public class Sport {

    private String name;
    private int imageId;

    public Sport(String name, int imageId) {
        this.name = name;
        this.imageId = imageId;
    }

    // 獲取項(xiàng)目名稱
    public String getName() {
        return name;
    }

    // 獲取項(xiàng)目圖片ID
    public int getImageId() {
        return imageId;
    }
}
  1. 為RecyclerView準(zhǔn)備一個(gè)適配器泻仙,新建SportAdapter類糕再,繼承自RecyclerView.adapter,適配器的泛型指定為內(nèi)部類SportAdapter.ViewHolder玉转。
public class SportAdapter extends RecyclerView.Adapter<SportAdapter.ViewHolder> {

    private List<Sport> sportList;

    // 靜態(tài)內(nèi)部類ViewHolder保存控件
    static class ViewHolder extends RecyclerView.ViewHolder {

        ImageView sportImage;
        TextView sportName;

        // item為RecyclerView子項(xiàng)的外層布局
        public ViewHolder(View itemView) {
            super(itemView);
            sportImage = itemView.findViewById(R.id.sport_image);
            sportName = itemView.findViewById(R.id.sport_name);
        }
    }

    // 傳入數(shù)據(jù)源sportList賦值給全局變量
    public SportAdapter(List<Sport> sportList) {
        this.sportList = sportList;
    }

    // 創(chuàng)建ViewHolder實(shí)例,先加載布局亿鲜,再把布局傳入viweHolder的實(shí)例中
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.sport_item, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    // 通過(guò)position獲取當(dāng)前實(shí)例,對(duì)于RecyclerView子項(xiàng)的數(shù)據(jù)進(jìn)行賦值
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Sport sport = sportList.get(position);
        holder.sportImage.setImageResource(sport.getImageId());
        holder.sportName.setText(sport.getName());
    }

    // RecyclerView的子項(xiàng)個(gè)數(shù)
    @Override
    public int getItemCount() {
        return sportList.size();
    }

}

  1. 修改MainActivity的代碼
public class MainActivity extends AppCompatActivity {

    private List<Sport> sportList = new ArrayList<>();

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

        // 初始化數(shù)據(jù)
        initSport();
        RecyclerView recyclerView = findViewById(R.id.recycler_view);

        // 為RecyclerView指定線性布局
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

        // 設(shè)置適配器
        SportAdapter adapter = new SportAdapter(sportList);
        recyclerView.setAdapter(adapter);
    }

    private void initSport() {
        for (int i = 0; i < 2; i++) {
            Sport archer = new Sport("archer", R.drawable.archer);
            sportList.add(archer);
            Sport athlete = new Sport("athlete", R.drawable.athlete);
            sportList.add(athlete);
            Sport badminton = new Sport("badminton", R.drawable.badminton);
            sportList.add(badminton);
            Sport bicycle = new Sport("bicycle", R.drawable.bicycle);
            sportList.add(bicycle);
            Sport diving = new Sport("diving", R.drawable.diving);
            sportList.add(diving);
            Sport fisher = new Sport("fisher", R.drawable.fisher);
            sportList.add(fisher);
            Sport pingpong = new Sport("pingpong", R.drawable.pingpong);
            sportList.add(pingpong);
            Sport swimming = new Sport("swimming", R.drawable.swimming);
            sportList.add(swimming);
            Sport volleyball = new Sport("volleyball", R.drawable.volleyball);
            sportList.add(volleyball);

        }
    }
}

這樣就實(shí)現(xiàn)了RecyclerView的縱向滾動(dòng)功能冤吨,效果圖如下:

image.png

三、實(shí)現(xiàn)橫向滾動(dòng)和瀑布流

實(shí)現(xiàn)橫向滾動(dòng)的效果

  1. 修改sport_item布局文件代碼,讓圖片和文字縱向排列,指定寬度讓每個(gè)item一樣大饶套。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="80dp"
    android:layout_height="wrap_content"
    android:showDividers="middle">

    <ImageView
        android:id="@+id/sport_image"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_gravity="center_horizontal"/>

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

</LinearLayout>
  1. 修改MainActivity漩蟆,在layoutManager中傳入LinearLayoutManager.HORIZONTAL
public class MainActivity extends AppCompatActivity {

    private List<Sport> sportList = new ArrayList<>();

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

        ... ...
        
        // 為RecyclerView指定線性布局
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);

        ... ...
    }

    ... ...
    }
}

這樣就實(shí)現(xiàn)了RecyclerView的橫向滾動(dòng)功能,效果圖如下:

image.png

RecyclerView因?yàn)樘峁┝薒ayoutManager,LayoutManager制定了一套可拓展的布局接口妓蛮,子類(例如LinearLayoutManager)只要按照接口來(lái)實(shí)現(xiàn)就可以呈現(xiàn)不同的效果怠李。
??除了LinearLayoutManager之外,RecyclerView還提供了GirdLayouManager實(shí)現(xiàn)網(wǎng)格布局和StaggeredGridLayoutManager實(shí)現(xiàn)瀑布流布局。

實(shí)現(xiàn)瀑布流的效果

  1. 修改sport_item的代碼,讓瀑布流的寬度根據(jù)布局列數(shù)自動(dòng)適配捺癞,讓文字居左顯示夷蚊。
<?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/sport_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

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

</LinearLayout>
  1. 修改MainActivity,指定RecyclerView的布局為StaggeredGrildLayout髓介,布局分為4列惕鼓。設(shè)置getRandomLengthName()來(lái)使每個(gè)item的文字段不一樣長(zhǎng),方便看出瀑布流效果唐础。
public class MainActivity extends AppCompatActivity {

    private List<Sport> sportList = new ArrayList<>();

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

        // 初始化數(shù)據(jù)
        initSport();
        RecyclerView recyclerView = findViewById(R.id.recycler_view);

        // 為RecyclerView指定線性布局
//        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        // 為RecyclerView指定4列的瀑布流布局
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(
                4, StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);

        // 設(shè)置適配器
        SportAdapter adapter = new SportAdapter(sportList);
        recyclerView.setAdapter(adapter);
    }

    // 寫(xiě)死的本地?cái)?shù)據(jù)
    private void initSport() {
        for (int i = 0; i < 3; i++) {
            Sport archer = new Sport(getRamdomLengthName("archer"), R.drawable.archer);
            sportList.add(archer);
            
            ... ...
            
            Sport volleyball = new Sport(getRamdomLengthName("volleyball"), R.drawable.volleyball);
            sportList.add(volleyball);

        }
    }

    // 把名稱copy隨機(jī)次形成一段文字箱歧,使每個(gè)item不一樣長(zhǎng)
    private String getRamdomLengthName(String sportName) {
        Random random = new Random();
        int length = random.nextInt(15) + 1;
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < length; i++) {
            builder.append(sportName);
        }
        return builder.toString();
    }
}

這樣就實(shí)現(xiàn)了RecyclerView的瀑布流布局,效果圖如下:

image.png

四一膨、RecyclerView的點(diǎn)擊事件

一般來(lái)說(shuō)呀邢,無(wú)論是ListView還是RecyclerView每個(gè)item都應(yīng)該有點(diǎn)擊事件,例如我們的新聞列表豹绪,點(diǎn)擊進(jìn)去應(yīng)該都有新聞內(nèi)容价淌。RecyclerView沒(méi)有像ListView一樣的API去setOnItemClickListener(),點(diǎn)擊事件由View去注冊(cè)瞒津,但也更加靈活了蝉衣。

  1. 修改apapter的代碼,在ViewHolder中添加view變量來(lái)保存item布局實(shí)例仲智,然后在onCreateViewHolder()中為item和image分別注冊(cè)不同的點(diǎn)擊事件买乃,由于image是item布局的子View,所以當(dāng)我們點(diǎn)擊事件的時(shí)候钓辆,image會(huì)攔截并處理點(diǎn)擊事件剪验,事件消耗完之后父View item的點(diǎn)擊事件就不會(huì)響應(yīng)。
public class SportAdapter extends RecyclerView.Adapter<SportAdapter.ViewHolder> {

    private List<Sport> sportList;

    // 靜態(tài)內(nèi)部類ViewHolder保存控件
    static class ViewHolder extends RecyclerView.ViewHolder {

        View sportView;

        public ImageView getSportImage() {
            return sportImage;
        }

        ImageView sportImage;
        TextView sportName;

        // item為RecyclerView子項(xiàng)的外層布局
        public ViewHolder(View itemView) {
            super(itemView);
            sportView = itemView;
            sportImage = itemView.findViewById(R.id.sport_image);
            sportName = itemView.findViewById(R.id.sport_name);
        }
    }

    // 傳入數(shù)據(jù)源sportList賦值給全局變量
    public SportAdapter(List<Sport> sportList) {
        this.sportList = sportList;
    }

    // 創(chuàng)建ViewHolder實(shí)例,先加載布局前联,再把布局傳入viweHolder的實(shí)例中
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.sport_item, parent, false);
        final ViewHolder holder = new ViewHolder(view);

        // 設(shè)置item項(xiàng)的點(diǎn)擊事件
        holder.sportView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int position = holder.getAdapterPosition();
                Sport sport = sportList.get(position);
                Toast.makeText(view.getContext(), "you click item " + sport.getName(),Toast.LENGTH_SHORT).show();
            }
        });

        // 設(shè)置image的點(diǎn)擊事件
        holder.sportImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int position = holder.getAdapterPosition();
                Sport sport = sportList.get(position);
                Toast.makeText(view.getContext(), "you click image " + sport.getName(),Toast.LENGTH_SHORT).show();
            }
        });

        return holder;
    }

    ... ...

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末功戚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子似嗤,更是在濱河造成了極大的恐慌啸臀,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烁落,死亡現(xiàn)場(chǎng)離奇詭異乘粒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)伤塌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門灯萍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人每聪,你說(shuō)我怎么就攤上這事旦棉〕莘纾” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵绑洛,是天一觀的道長(zhǎng)救斑。 經(jīng)常有香客問(wèn)我,道長(zhǎng)真屯,這世上最難降的妖魔是什么脸候? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮讨跟,結(jié)果婚禮上纪他,老公的妹妹穿的比我還像新娘。我一直安慰自己晾匠,他們只是感情好茶袒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著凉馆,像睡著了一般薪寓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上澜共,一...
    開(kāi)封第一講書(shū)人閱讀 51,718評(píng)論 1 305
  • 那天向叉,我揣著相機(jī)與錄音,去河邊找鬼嗦董。 笑死母谎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的京革。 我是一名探鬼主播奇唤,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼匹摇!你這毒婦竟也來(lái)了咬扇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤廊勃,失蹤者是張志新(化名)和其女友劉穎懈贺,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體坡垫,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梭灿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了冰悠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堡妒。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖屿脐,靈堂內(nèi)的尸體忽然破棺而出涕蚤,到底是詐尸還是另有隱情,我是刑警寧澤的诵,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布万栅,位于F島的核電站,受9級(jí)特大地震影響西疤,放射性物質(zhì)發(fā)生泄漏烦粒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一代赁、第九天 我趴在偏房一處隱蔽的房頂上張望扰她。 院中可真熱鬧,春花似錦芭碍、人聲如沸徒役。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)忧勿。三九已至,卻和暖如春瞻讽,著一層夾襖步出監(jiān)牢的瞬間鸳吸,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工速勇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晌砾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓烦磁,卻偏偏與公主長(zhǎng)得像养匈,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子个初,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,180評(píng)論 25 707
  • 這篇文章分三個(gè)部分乖寒,簡(jiǎn)單跟大家講一下 RecyclerView 的常用方法與奇葩用法;工作原理與ListView比...
    LucasAdam閱讀 4,391評(píng)論 0 27
  • 又到了更新博文的時(shí)間了院溺,最近在看一本很不錯(cuò)的心理學(xué)書(shū)籍楣嘁,名字叫做 《拖延心理學(xué)》,封面長(zhǎng)下面這樣子 書(shū)的內(nèi)容主要是...
    ec95b5891948閱讀 57,483評(píng)論 38 472
  • 在這個(gè)充滿夢(mèng)想的時(shí)代珍逸, 有這樣一個(gè)逐夢(mèng)的地方逐虚; 在這個(gè)物欲橫流的社會(huì), 有這樣一個(gè)潛心讀書(shū)的地方谆膳; 在這個(gè)創(chuàng)業(yè)創(chuàng)新...
    絲美天下閱讀 138評(píng)論 0 0
  • 最難日當(dāng)頭叭爱, 千金扇不休。 暮時(shí)友閑語(yǔ)漱病, 方知已入秋买雾。 每天最不好受的時(shí)間是日頭在頭頂?shù)臅r(shí)候把曼, 就算你給我很多錢讓...
    伯澤閱讀 322評(píng)論 3 5