今天的實作打算來聊聊根ViewPager有關的東西

ViewPager這東西其實就是"左/右滑動視窗"的元件(・ωー)~☆

這類的元件在購物網站上很常見到,像是蝦皮拍賣的主頁面就是了

蝦皮拍賣: 隨拍即賣蝦米都賣|不限時間玩購物App-APP試玩

 

那麼,有左滑~右滑~

有沒有上滑~下滑~呢?

 

答案是有的齁...只是我一時找不到有哪個APP是用這個UI (;´д`)ゞ

 

好啦不管啦我說有就是有咩(╯=▃=)╯︵┻━┻

 

那麼所以今天的主題就是來做一個直向式的ViewPager+索引欄位(Tab)的實作

來看今天範例

 

然後是Github

->https://github.com/thumbb13555/VerticalViewPagerWithTabs/tree/master

 

那就讓我們開始吧

 


 

1. 專案結構介紹與概要

 

今天的主題是直向式滾動的ViewPager+Tab索引之介紹

那麼實作方法簡單來說就是改造一個ViewPager元件+RecyclerView元件來達成目標

所以今天會用到的技術便是以下技術的綜合型運用

1. RecyclerView

2. ViewPager

3. interface回調接口設置

4. Fargment

 

除了4之外...4不知道也沒差啦(聳肩

其他的技術不會不熟沒聽過的通通給我回去看這些文章!!!!

->碼農日常-『Android studio』ViewPager+tabLayout(左右滑動視窗)之基本用法

->碼農日常-『Android studio』NumberPicker 配合 Interface (接口)完成一個時間選擇器

->碼農日常-『Android studio』基本RecyclerView用法

 

會的也幫我點閱一下~霸偷(┼д┼;)

貓咪- 網友相關創作

 

對~~給我灌灌(*ノω<*)!!

 

咳咳扯遠了...

 

總之不會的就幫我去看一下吧

再來是專案結構的部分,用圖片介紹比較快

截圖 2020-10-10 下午9.31.55

 

其關係圖為

截圖 2020-10-10 下午9.51.54

 

 

另外的三個介面則分別是

1. activity_main.xml -> 主介面樣式

2. page_item -> ViewPager裡面的樣式

3. tabs_item -> RecyclerView裡面的樣式

 


 

2. 畫介面

 

這次的介面如下

Screenshot_1602324104

 

基本上,左側綠色就是用RecyclerView所完成的Tab欄位

而白色區域則全部都是ViewPager

也因此主畫面就是一個RecyclerView+ViewPager而已

 

那就上介面囉

 

activity_main.xml

 

截圖 2020-10-11 上午12.19.45

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="100dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="#8BC34A"
        />

    <com.jetec.verticalviewpagerwithtabs.VerticalViewPager
        android:id="@+id/pager"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toEndOf="@+id/recyclerView"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

這時候我標註的紅字地方應該編輯器上也是紅字,這部分暫時略過

我們下一個段落就要來寫他了

 

page_item

 

截圖 2020-10-11 上午12.29.01

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView_PageTag"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="第X頁"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView_Info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView_PageTag" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

tabs_item

 

截圖 2020-10-11 上午12.30.24

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="#8BC34A"
    android:foreground="?attr/selectableItemBackground"
    >

    <TextView
        android:id="@+id/textView_TabNumber"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="水果"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        android:textColor="@android:color/white"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

除了剛才我說略過的地方之外,介面應該都處理好了

那麼接下來因為程式較複雜,我會階段性地完成實作

請各位要有耐心往下做喔!(´∀`)

 


 

3. VerticalViewPager.java

 

首先我們要先把上一段紅字的部分把它補起來

其錮中緣由就是在這個檔案啦!

我一樣PO全部,再來從中畫重點

 

VerticalViewPager.java

/**製作一個介面,將介面繼承自ViewPager後,使之被滑動以及觸碰手勢顛倒*/
public class VerticalViewPager extends ViewPager {
    public VerticalViewPager(@NonNull Context context) {
        super(context);
        init();
    }

    public VerticalViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    /**設置頁面變為上下滑動*/
    private void init() {
        setPageTransformer(true, new PageTransformer());
        setOverScrollMode(View.OVER_SCROLL_NEVER);
    }
    /**複寫ViewPager本身的的手勢操作*/
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean interceped = super.onInterceptTouchEvent(swapXY(ev));
        swapXY(ev);
        return interceped;
    }
    /**複寫ViewPager在整體畫面中的手勢操作*/
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(swapXY(ev));
    }
    /**決定畫面XY軸的變化*/
    private MotionEvent swapXY(MotionEvent ev) {
        float width, height, newX, newY;
        width = (float) getWidth();
        height = (float) getHeight();
        newX = ev.getY() / height * width;
        newY = ev.getX() / width * height;
        ev.setLocation(newX,newY);
        return ev;
    }
    /**設置ViewPager頁面跑動的方式,使原本左右的方式改為上下的方式*/
    private class PageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(@NonNull View page, float position) {
            if (position < -1) {
                page.setVisibility(View.VISIBLE);
            } else if (position <= 1) {
                page.setVisibility(View.VISIBLE);
                page.setTranslationX(page.getWidth() * -position);
                Float y = position * page.getHeight();
                page.setTranslationY(y);
            } else {
                page.setVisibility(View.INVISIBLE);
            }
        }
    }
}

 

 

好吧...如果真要畫重點那應該會變成這樣

image

 

反正~你要整個抄走也OK

但是粉底白字的Public一定要寫喔!不然你前面死都會抓不到

 

我還有標註藍底白字的部分,那部分就是使ViewPager滑動的方向從原先的左右滑動改成上下滑動

再來是兩個覆寫onInterceptTouchEvent()onTouchEvent()部分

/**複寫ViewPager本身的的手勢操作*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    boolean interceped = super.onInterceptTouchEvent(swapXY(ev));
    swapXY(ev);
    return interceped;
}
/**複寫ViewPager在整體畫面中的手勢操作*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
    return super.onTouchEvent(swapXY(ev));
}
/**決定畫面XY軸的變化*/
private MotionEvent swapXY(MotionEvent ev) {
    float width, height, newX, newY;
    width = (float) getWidth();
    height = (float) getHeight();
    newX = ev.getY() / height * width;
    newY = ev.getX() / width * height;
    ev.setLocation(newX,newY);
    return ev;
}

 

 

這兩個在註解也有寫到,基本上就是用來偵測使用者手指滑動的複寫

然後運用我自己寫的副程式swapXY調整滑動方向,便是完成。

 

這時候回到介面去看,應該就會正常囉(沒正常的話重打Vertical...應該就會跑出來了)

 


 

4. 先完成ViewPager的部份

 

這一段落的目標,我們是要完成到這個部分

 

基本上就是這兩個檔案

 

截圖 2020-10-11 上午1.00.46

 

我們先從最下面嫩草綠PagerFragment.java開始做吧

 

老樣子,先全部

 

PagerFragment.java

 

public class PagerFragment extends Fragment {

    private int pagerId = 0;
    private String info = "";
    private static final String KEY_PAGE_ID = "key_page_id";
    private static final String KEY_INFO = "key_Info";

    /**設置初始化接口,並將指定要載入的資料存起來*/
    public static PagerFragment newInstance(String s, int pageId){
        /**以Bundle存放要被載入的資料,稍後再onCreate中取出*/
        Bundle args = new Bundle();
        args.putString(KEY_INFO,s);
        args.putInt(KEY_PAGE_ID,pageId);
        PagerFragment fragment = new PagerFragment();
        fragment.setArguments(args);
        return fragment;

    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /**取出儲存的資料*/
        Bundle bundle = getArguments();
        pagerId = bundle.getInt(KEY_PAGE_ID);
        info = bundle.getString(KEY_INFO);

    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        /**找到View, 並設置裡面的UI要做的事*/
        View view = inflater.inflate(R.layout.page_item,container,false);
        TextView tvTag = view.findViewById(R.id.textView_PageTag);
        TextView tvInfo = view.findViewById(R.id.textView_Info);

        tvTag.setText("第"+(pagerId+1)+"頁");
        tvInfo.setText(info);

        return view;
    }
}

 

這邊只有三個程式區塊

分別為newInstance,以及覆寫的onCreateonCreateView

 

而其實...Fragment也有生命週期滴 (咦??( ・ὢ・ )

 

底加↓

 

整體上來說Fragment的生命週期跟一般的Activity的生命週期有一點點接近

但又有一些一般Activity生命週期中沒有的東西

詳細的部分我就不多說了...真要說起來又是一篇文章( ̄ー ̄;

此處只有用到onCreateonCreateView就好

 

本篇中我們把onCreate放入獲取資料的部分,而資料來源就是在newInstance中預先加載資料,並藉由Bundel傳遞

最後才在onCreateView中獲取相關的layout跟其配置的UI們,並加以操作

 

喔對了,粉底白字的Public也記得要加入喔!不然會閃退

 

做到這邊預備工作完成了,再來是ViewPagerAdapter.java的部分

截圖 2020-10-11 上午1.00.46

也就是藍色底(右)的部分

 

ViewPagerAdapter.java

 

class ViewPagerAdapter extends FragmentPagerAdapter {

    private String[] strings;

    /**建構子初始化*/
    public ViewPagerAdapter(@NonNull FragmentManager fm, String[] strings) {
        super(fm);
        this.strings = strings;
    }

    /**此功能在本範例中未使用*/
    /**若要做即時資料更新時便可以使用此方法*/
    public void updateData(String[] strings){
        this.strings = strings;
        notifyDataSetChanged();
    }

    /**此功能在本範例中未使用*/
    /**若有即時資料更新的需求,除了使用notifyDataSetChanged(),也必須要在這邊做getItemPosition的複寫*/
    @Override
    public int getItemPosition(@NonNull Object object) {
        if (object instanceof PagerFragment){
            return PagerAdapter.POSITION_NONE;
        }
        return super.getItemPosition(object);
    }

    /**設置每個Page的內容*/
    @NonNull
    @Override
    public Fragment getItem(int position) {
        PagerFragment pagerFragment = PagerFragment.newInstance(
                strings[position],position);

        return pagerFragment;
    }
    /**決定要設置幾個Page*/
    @Override
    public int getCount() {
        return strings.length;
    }
}

 

Adapter的內容,其實跟RecyclerView的Adapter的內容有異曲同工之妙

每個部分的內容我也有寫在註解喔

這部分除了getItem的部分之外就比較沒要很注意的地方了

 

這邊可以特別注意灰字updateData()getItemPosition()兩個部分

 

簡單粗暴的文章在這裡->https://www.acoro.net/android-viewpager-notifydatasetchanged/

詳細點的文章在這裡->https://www.jianshu.com/p/266861496508

 

這部分就是如果你的ViewPager內有需要被即時更新的元件時,可以調用的一個接口

無論你會不會用到,總之就放著有備無患吧(・ωー)~☆

 

最後來到MainActivity.java

使用這個我們做好的模組吧(・ω・)b

 

public class MainActivity extends AppCompatActivity  {

    ViewPagerAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /**製作陣列*/
        String[] strings = {"香蕉","蘋果","鳳梨","橘子","蓮霧"};
        /**設置ViewPager*/
        final VerticalViewPager viewPager = findViewById(R.id.pager);
        /**綁定ViewPager給ViewPagerAdapter*/
        pagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),strings);
        viewPager.setAdapter(pagerAdapter);
       
    }
    
}

 

模組上上去後,應該就可以出現我們要的效果囉:D

 

 


 

5. 再來是完成左邊的標籤欄位(Tabs)的部分

 

這段我們要把左邊的標籤欄位給完成

這部分的原理其實很簡單

他就是個RecyclerView而已(-‿◦)

 

什麼Σ(・口・)你說沒聽過?我不會?聽不懂?

給我回去點閱โ๏∀๏ใ

->碼農日常-『Android studio』基本RecyclerView用法

 

咳咳...總之就是個RecyclerView

 

既然有RecyclerView,那便有其對應的Adapter

於是,其對應的Adapter就是我們的TabsAdapter.java

 

class TabsAdapter extends RecyclerView.Adapter<TabsAdapter.ViewHolder> {
    
    private String[] strings;
    private RecyclerView recyclerView;
    private int currentPage = 0;

    /**建構子*/
    public TabsAdapter(String[] strings,RecyclerView recyclerView) {
        this.strings = strings;
        this.recyclerView = recyclerView;
    }
   
    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvTab;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            tvTab = itemView.findViewById(R.id.textView_TabNumber);
        }
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.tabs_item,parent,false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
        holder.tvTab.setText(strings[position]);
       
    }

    @Override
    public int getItemCount() {
        return strings.length;
    }

}

 

再來,一樣來到MainActivity.java來使用它

 

public class MainActivity extends AppCompatActivity  {

    TabsAdapter tabAdapter;
    ViewPagerAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /**製作陣列*/
        String[] strings = {"香蕉","蘋果","鳳梨","橘子","蓮霧"};
        /**設置ViewPager*/
        final VerticalViewPager viewPager = findViewById(R.id.pager);
        /**綁定ViewPager給ViewPagerAdapter*/
        pagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),strings);
        viewPager.setAdapter(pagerAdapter);
        /**監聽ViewPager被滑動時的事件處理*/
        viewPager.addOnPageChangeListener(onPageChangeListener);

        /**設置RecyclerView*/
        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        tabAdapter = new TabsAdapter(strings,recyclerView);
        recyclerView.setAdapter(tabAdapter);
      
    }    
}

 

自此請執行一下,就可以看到左邊的標籤欄位出現囉

截圖 2020-10-11 下午12.46.37

 


 

6. 撰寫Tab點擊後ViewPager的換頁

 

接下來的6跟7大段要來處理關於"點擊標籤後ViewPager的連動"以及"ViewPager上下滑動後標籤的變換"兩個部分

在這段我要來先完成點擊Tab後換頁的功能

如圖

 

這個部分的話,基本上就是要來秀一波RecyclerView的點擊操作了

上程式!

 

TabsAdapter.java

 

class TabsAdapter extends RecyclerView.Adapter<TabsAdapter.ViewHolder> {
    OnTabClick onTabClick;
    private String[] strings;
    private RecyclerView recyclerView;
    private int currentPage = 0;

    /**建構子*/
    public TabsAdapter(String[] strings,RecyclerView recyclerView) {
        this.strings = strings;
        this.recyclerView = recyclerView;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvTab;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            tvTab = itemView.findViewById(R.id.textView_TabNumber);
        }
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.tabs_item,parent,false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
        holder.tvTab.setText(strings[position]);      
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onTabClick.onTabClick(position);
            }
        });
    }

    @Override
    public int getItemCount() {
        return strings.length;
    }

    interface OnTabClick{
        void onTabClick(int position);
    }
}

 

然後來到MainActivity.java

public class MainActivity extends AppCompatActivity  {

    TabsAdapter tabAdapter;
    ViewPagerAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /**製作陣列*/
        String[] strings = {"香蕉","蘋果","鳳梨","橘子","蓮霧"};
        /**設置ViewPager*/
        final VerticalViewPager viewPager = findViewById(R.id.pager);
        /**綁定ViewPager給ViewPagerAdapter*/
        pagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),strings);
        viewPager.setAdapter(pagerAdapter);javascript:void('FFFFFF')
        /**監聽ViewPager被滑動時的事件處理*/
        viewPager.addOnPageChangeListener(onPageChangeListener);

        /**設置RecyclerView*/
        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        tabAdapter = new TabsAdapter(strings,recyclerView);
        recyclerView.setAdapter(tabAdapter);
        /**點擊RecyclerView的Tab時將ViewPager滾動至該頁*/
        tabAdapter.onTabClick = new TabsAdapter.OnTabClick() {
            @Override
            public void onTabClick(int position) {
                viewPager.setCurrentItem(position,true);
            }
        };
    }
}

 

至此為止,粉底白字的部分都是屬於interface之點擊回調的應用

也就是這篇的內容

->碼農日常-『Android studio』NumberPicker 配合 Interface (接口)完成一個時間選擇器

 

至於綠底白字的部分,就是設置ViewPage抵達所指定的頁數的程式囉

 


 

7. 撰寫上下滑動時標籤跟著做動的部分

 

Okay終於來到最後一段了

這一段結束就可以下班囉(;´д`)ゞ

首先,先來寫ViewPager端滑動時給RecyclerView標籤做動的街口

 

TabsAdapter.java

 

class TabsAdapter extends RecyclerView.Adapter<TabsAdapter.ViewHolder> {
    OnTabClick onTabClick;
    private String[] strings;
    private RecyclerView recyclerView;
    private int currentPage = 0;

    /**建構子*/
    public TabsAdapter(String[] strings,RecyclerView recyclerView) {
        this.strings = strings;
        this.recyclerView = recyclerView;
    }
    /**請從這邊開始複製↓*/
    /**提供一個接口給外部以綁定ViewPager的頁數及Tab顯示*/
    public void setCurrentPage(int position){
        if (currentPage >= 0){
            deSelect(currentPage);
        }
        /**從position中找到itemView*/
        View targetView = recyclerView.getLayoutManager().findViewByPosition(position);
        TextView tvTab = targetView.findViewById(R.id.textView_TabNumber);
        setTextViewSelected(tvTab);
        /**保證RecyclerViewAdapter中的即時頁碼與被滑到的位置相同*/
        currentPage = position;
    }
    /**使其他沒被滑到會點選到的頁面Tab回復原本的顏色*/
    private void deSelect(int position){
        if (recyclerView.getLayoutManager().findViewByPosition(position)!= null){
            View targetView = recyclerView.getLayoutManager().findViewByPosition(position);
            TextView tvTab = targetView.findViewById(R.id.textView_TabNumber);
            setTextViewUnSelected(tvTab);
        }
        currentPage = -1;
    }
    /**設置被選到時的UI變化*/
    private void setTextViewSelected(TextView tvTab){
        tvTab.setTextColor(Color.RED);
    }
    /**設置被未被選到時的UI變化*/
    private void setTextViewUnSelected(TextView tvTab){
        tvTab.setTextColor(Color.WHITE);
    }
/**複製到這邊↑*/
    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvTab;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            tvTab = itemView.findViewById(R.id.textView_TabNumber);
        }
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.tabs_item,parent,false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
        holder.tvTab.setText(strings[position]);
        if (position == currentPage) setTextViewSelected(holder.tvTab);
        else setTextViewUnSelected(holder.tvTab);

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onTabClick.onTabClick(position);
            }
        });
    }

    @Override
    public int getItemCount() {
        return strings.length;
    }

    interface OnTabClick{
        void onTabClick(int position);
    }
}

 

挖..看起來好複雜

其實真相難點只有一個

 

就在這裡

/**提供一個接口給外部以綁定ViewPager的頁數及Tab顯示*/
public void setCurrentPage(int position){
    if (currentPage >= 0){
        deSelect(currentPage);
    }
    /**從position中找到itemView*/
    View targetView = recyclerView.getLayoutManager().findViewByPosition(position);
    TextView tvTab = targetView.findViewById(R.id.textView_TabNumber);
    setTextViewSelected(tvTab);
    /**保證RecyclerViewAdapter中的即時頁碼與被滑到的位置相同*/
    currentPage = position;
}

 

這裡是我當時找資料找得比較久的地方(汗

因為基本上在RecyclerView設置完後,究竟要如何針對單一item進行小部分修改

這是當時一直困擾我的問題

而且坦白說我當時在找資料時大部分的實作也都是ViewPager搭配ListView實作的

ViewPager搭配RecyclerView的根據我的小數據目前還很少看到QQ

所以為了找出獲取的方法,我也是嘗試了很久..

 

Okay, 反正我做出來了就好-3-

 

那麼最後的最後,就來把功能連動起來啦!

 

回到MainActivity

 

MainActivity.java

 

public class MainActivity extends AppCompatActivity  {

    TabsAdapter tabAdapter;
    ViewPagerAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /**製作陣列*/
        String[] strings = {"香蕉","蘋果","鳳梨","橘子","蓮霧"};
        /**設置ViewPager*/
        final VerticalViewPager viewPager = findViewById(R.id.pager);
        /**綁定ViewPager給ViewPagerAdapter*/
        pagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(),strings);
        viewPager.setAdapter(pagerAdapter);
        /**監聽ViewPager被滑動時的事件處理*/
        viewPager.addOnPageChangeListener(onPageChangeListener);

        /**設置RecyclerView*/
        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        tabAdapter = new TabsAdapter(strings,recyclerView);
        recyclerView.setAdapter(tabAdapter);
        /**點擊RecyclerView的Tab時將ViewPager滾動至該頁*/
        tabAdapter.onTabClick = new TabsAdapter.OnTabClick() {
            @Override
            public void onTabClick(int position) {
                viewPager.setCurrentItem(position,true);
            }
        };

    }
    /**監聽ViewPager被滑動時的事件處理*/
    private ViewPager.OnPageChangeListener onPageChangeListener= new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
        /**抓取到被滑動到的那一頁*/
        @Override
        public void onPageSelected(int position) {
            tabAdapter.setCurrentPage(position);
        }
        @Override
        public void onPageScrollStateChanged(int state) {}
    };


}

 

MainActivity中,需要加入的就是偵聽ViewPager有被滑動的事件

也就是addOnPageChangeListener的部分

 

取得到所被選擇到的頁面位置position後,便在綠底白字的部分

如此一來便完成雙向的連動綁定囉!

 


 

結語

 

花了七個段落...終於是讓我給寫完了QQ

今天的內容很長,除了你看得很累,我寫得也很累RRRRR

 

不過是因為剛好遇到10月國慶連假的緣故,所以才花了大把時間來完成這項功能

而這項功能也如同我的文章長度還有我的下半身某個器官長度一樣,花了我大把時間研究的呀

 

...我說我的腿長(*ノω<*)

那麼希望我的文章對你有幫助,打文章很辛苦,請不吝幫我按個推推跟讚賞公民拍手五下吧!

TK

arrow
arrow

    碼農日常 發表在 痞客邦 留言(5) 人氣()