欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義引導(dǎo)玩轉(zhuǎn)ViewPager的方法詳解

 更新時(shí)間:2019年06月06日 11:01:28   作者:Android架構(gòu)  
這篇文章主要給大家介紹了關(guān)于Android自定義引導(dǎo)玩轉(zhuǎn)ViewPager的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

ViewPager簡(jiǎn)介:

ViewPager(android.support.v4.view.ViewPager)是android擴(kuò)展包v4包中的類,這個(gè)類可以讓用戶左右切換當(dāng)前的view,實(shí)現(xiàn)滑動(dòng)切換的效果。

注意:

ViewPager類直接繼承了ViewGroup類,也就是說(shuō)它和我們經(jīng)常打交道的LinearLayout一樣,都是一個(gè)容器,需要在里面添加我們想要顯示的內(nèi)容。

  ViewPager類需要一個(gè)PagerAdapter適配器類給它提供數(shù)據(jù),這個(gè)和ListView類似。

ViewPager基礎(chǔ)使用

具體步驟:

1.在布局文件里加入

 <android.support.v4.view.ViewPager
  android:id="@+id/in_viewpager"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
 </android.support.v4.view.ViewPager>

2.在Activity中加載要顯示的Views,通過(guò)動(dòng)態(tài)加載布局得到一個(gè)個(gè)View

  mViewList = new ArrayList<View>();
  LayoutInflater lf = getLayoutInflater().from(MainActivity.this);
  View view1 = lf.inflate(R.layout.we_indicator1, null);
  View view2 = lf.inflate(R.layout.we_indicator2, null);
  View view3 = lf.inflate(R.layout.we_indicator3, null);
  mViewList.add(view1);
  mViewList.add(view2);
  mViewList.add(view3);

3.自定義PagerAdapter,以便將步驟2中的Views數(shù)據(jù)加載到ViewPager容器中

public class ViewPagerAdatper extends PagerAdapter {
 private List<View> mViewList ;

 public ViewPagerAdatper(List<View> mViewList ) {
  this.mViewList = mViewList;
 }

 @Override
 public int getCount() {
  return mViewList.size();
 }

 @Override
 public boolean isViewFromObject(View view, Object object) {
  return view==object;
 }

 @Override
 public Object instantiateItem(ViewGroup container, int position) {
  container.addView(mViewList.get(position));
  return mViewList.get(position);
 }

 @Override
 public void destroyItem(ViewGroup container, int position, Object object) {
  container.removeView(mViewList.get(position));
 }
}

4.將ViewPager和自定義的PagerAdapter關(guān)聯(lián)起來(lái)

mIn_vp.setAdapter(new ViewPagerAdatper(mViewList));

通過(guò)簡(jiǎn)單使用ViewPager,得到的展示效果,僅僅支持左右滑動(dòng),效果比較單一。

ViewPager進(jìn)階使用——實(shí)現(xiàn)跟隨式小圓點(diǎn)效果

步驟:

1.添加小圓點(diǎn)

在布局中的設(shè)置如下:

<RelativeLayout
  android:id="@+id/rl_dots"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true"
  android:layout_centerHorizontal="true"
  android:layout_marginBottom="60dp">

  <LinearLayout
   android:id="@+id/in_ll"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:orientation="horizontal">
  </LinearLayout>

  <ImageView
   android:id="@+id/iv_light_dots"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:src="@drawable/light_dot"/>
 </RelativeLayout>

隨后在LinearLayout中動(dòng)態(tài)添加3個(gè)小黑點(diǎn),小白點(diǎn)默認(rèn)覆蓋在第一個(gè)小黑點(diǎn)的上面。

在Activity中的添加小黑點(diǎn),代碼如下:

private void addDots() {
  mOne_dot = new ImageView(this);
  mOne_dot.setImageResource(R.drawable.gray_dot);
  LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
  layoutParams.setMargins(0, 0, 40, 0);
  mIn_ll.addView(mOne_dot, layoutParams);
  mTwo_dot = new ImageView(this);
  mTwo_dot.setImageResource(R.drawable.gray_dot);
  mIn_ll.addView(mTwo_dot, layoutParams);
  mThree_dot = new ImageView(this);
  mThree_dot.setImageResource(R.drawable.gray_dot);
  mIn_ll.addView(mThree_dot, layoutParams);
  setClickListener();

 }

2.獲得兩個(gè)點(diǎn)之間的距離

實(shí)現(xiàn)小白點(diǎn)動(dòng)態(tài)跟隨的思路是:根據(jù)頁(yè)面的移動(dòng)情況,通過(guò)設(shè)置小白點(diǎn)的 leftMargin 實(shí)現(xiàn)小紅點(diǎn)的動(dòng)態(tài)跟隨。因此首要的是獲得兩個(gè)點(diǎn)之間的距離,根據(jù)頁(yè)面移動(dòng)到的位置,進(jìn)行相應(yīng)的運(yùn)算。

需要注意的是:在onCreate()中直接獲得小白點(diǎn)的左邊距 getLeft()結(jié)果為0,這是因?yàn)閂iew組件布局要在onResume回調(diào)后完成。

因此使用另一種方法:

mLight_dots.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
      @Override
      public void onGlobalLayout() {
        //獲得兩個(gè)圓點(diǎn)之間的距離
        mDistance = mIn_ll.getChildAt(1).getLeft() - mIn_ll.getChildAt(0).getLeft();
        mLight_dots.getViewTreeObserver()
            .removeGlobalOnLayoutListener(this);
      }
    });

在布局發(fā)生改變或者某個(gè)視圖的可視狀態(tài)發(fā)生改變時(shí)調(diào)用該事件。但此方法會(huì)被多次調(diào)用,因此需要在獲取到視圖的寬度和高度后執(zhí)行 remove 方法移除該監(jiān)聽(tīng)事件。

3.監(jiān)聽(tīng)頁(yè)面的移動(dòng)情況

 mIn_vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        //頁(yè)面滾動(dòng)時(shí)小白點(diǎn)移動(dòng)的距離,并通過(guò)setLayoutParams(params)不斷更新其位置
        float leftMargin = mDistance * (position + positionOffset);
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mLight_dots.getLayoutParams();
        params.leftMargin = (int) leftMargin;
        mLight_dots.setLayoutParams(params); 
      }

      @Override
      public void onPageSelected(int position) {
        //頁(yè)面跳轉(zhuǎn)時(shí),設(shè)置小圓點(diǎn)的margin
        float leftMargin = mDistance * position;
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mLight_dots.getLayoutParams();
        params.leftMargin = (int) leftMargin;
        mLight_dots.setLayoutParams(params);
      }

      @Override
      public void onPageScrollStateChanged(int state) {

      }
    });
  }

在頁(yè)面移動(dòng)過(guò)程中,根據(jù)mDistance * (position + positionOffset) 可以實(shí)時(shí)更新小白點(diǎn)的位置

這部分內(nèi)容加入了一個(gè)新的功能 點(diǎn)擊小黑點(diǎn) 可以直接跳轉(zhuǎn)到對(duì)應(yīng)的引導(dǎo)頁(yè)面,具體邏輯就是在小黑點(diǎn)的點(diǎn)擊事件中加入如下代碼:

 mIn_vp.setCurrentItem(1);

在頁(yè)面選擇過(guò)程中,根據(jù)mDistance * position可以實(shí)時(shí)小紅點(diǎn)的位置

4.跳轉(zhuǎn)按鈕的實(shí)現(xiàn)

具體邏輯:到引導(dǎo)頁(yè)到達(dá)最后一頁(yè)時(shí),跳轉(zhuǎn)到主頁(yè)的按鈕出現(xiàn)。其他情況為隱藏狀態(tài)
因此可以在onPageScrolled(int position, float positionOffset, int positionOffsetPixels)和onPageSelected(int position)方法中加入如下代碼:

         if(position==2){
          mBtn_next.setVisibility(View.VISIBLE);
        }

當(dāng)按照從第一頁(yè)到最后一頁(yè),然后點(diǎn)擊按鈕跳轉(zhuǎn)到首頁(yè),則以上邏輯足夠。

但當(dāng)用戶瀏覽到最后一頁(yè)后再回轉(zhuǎn)到前面感興趣的頁(yè)面,則會(huì)出現(xiàn)按鈕依舊出現(xiàn)的情況,不符合要求。因此要完善邏輯,加入新的判斷,邏輯如下:

if(position!=2&&mBtn_next.getVisibility()==View.VISIBLE){
          mBtn_next.setVisibility(View.GONE);
        }

以上邏輯保證了按鈕的正常顯示,剩下的就可以具體操作,實(shí)現(xiàn)跳轉(zhuǎn)到首頁(yè)的邏輯。

ViewPager進(jìn)階使用——自定義炫酷動(dòng)畫(huà)

ViewPager自帶了一個(gè)setPageTransformer用于設(shè)置切換動(dòng)畫(huà)~

setPageTransformer (boolean reverseDrawingOrder, PageTransformer transformer)需要傳入兩個(gè)參數(shù)

第一個(gè)參數(shù):如果為true,則表明自定義的pageTransformer需要 page view從后到前的順序繪制,反之則為false。

第二個(gè)參數(shù):傳入一個(gè)自定義的pageTransformer對(duì)象

因此實(shí)現(xiàn)炫酷動(dòng)畫(huà)的關(guān)鍵點(diǎn)就在于:自定義pageTransformer

Google官方給我們展示了兩個(gè)動(dòng)畫(huà)例子:DepthPageTransformer和ZoomOutPageTransformer,比較炫。我們就以Google官方的例子來(lái)學(xué)習(xí)自定義pageTransformer,以此為基礎(chǔ),我們可以自定義各種各樣的動(dòng)畫(huà)實(shí)現(xiàn)效果。

1.PageTransformer中position解析

自定義PageTransformer只需要實(shí)現(xiàn)一個(gè)方法,transformPage(View page, float position),而這個(gè)方法實(shí)現(xiàn)的關(guān)鍵就是對(duì)position的理解。

源碼中的注釋解釋如下:

Apply the transformation to this page

position - Position of page relative to the current front-and-center position of the pager. 0 is front and center. 1 is one full page position to the right, and -1 is one page position to the left.

我們可以理解為:

  • 0表示當(dāng)前頁(yè)面,是當(dāng)前頁(yè)面
  • -1表示左側(cè)的頁(yè)面,是左側(cè)頁(yè)面
  • 1表示右側(cè)的頁(yè)面,是右側(cè)頁(yè)面

在用戶滑動(dòng)界面的時(shí)候,position是動(dòng)態(tài)變化的,下面以左滑為例:

  • 選中頁(yè)面 position:0->-1
  • 前一個(gè)item position:-1 -> -2
  • 后一個(gè)item position:1 -> 0

但是當(dāng)ViewPager設(shè)置pageMargin,設(shè)置兩個(gè)頁(yè)面之間的距離(通過(guò)調(diào)用viewPager.setPageMargin()方法設(shè)置)后,情況則不同。

如果你設(shè)置了pageMargin,前后頁(yè)面的position需要分別加上(或減去,前減后加)一個(gè)偏移量(偏移量的計(jì)算方式為pageMargin / pageWidth)。

同樣以左滑為例:

  • 選中頁(yè)面position:0->-1 - pageMargin / pageWidth
  • 前一個(gè)item position:-1 - pageMargin / pageWidth -> -2 - pageMargin / pageWidth
  • 后一個(gè)item position:1 + pageMargin / pageWidth -> 0

因此我們可以將position的值應(yīng)用于setAlpha(), setTranslationX(), 或者 setScaleY()等等方法,從而實(shí)現(xiàn)自定義的動(dòng)畫(huà)效果。

2.實(shí)現(xiàn)transformPage(View page, float position)方法

public class DepthPageTransformer implements ViewPager.PageTransformer {
  private static final float MIN_SCALE = 0.75f;
  @Override
  public void transformPage(View page, float position) {
    int pageWidth = page.getWidth();
    if (position < -1) { // [-Infinity,-1)
      // 頁(yè)面遠(yuǎn)離左側(cè)頁(yè)面
      page.setAlpha(0);
    } else if (position <= 0) { // [-1,0]
      // 頁(yè)面在由中間頁(yè)滑動(dòng)到左側(cè)頁(yè)面 或者 由左側(cè)頁(yè)面滑動(dòng)到中間頁(yè)
      page.setAlpha(1);
      page.setTranslationX(0);
      page.setScaleX(1);
      page.setScaleY(1);
    } else if (position <= 1) { // (0,1]
      //頁(yè)面在由中間頁(yè)滑動(dòng)到右側(cè)頁(yè)面 或者 由右側(cè)頁(yè)面滑動(dòng)到中間頁(yè)
      // 淡入淡出效果
      page.setAlpha(1 - position);
      // 反方向移動(dòng)
      page.setTranslationX(pageWidth * -position);
      // 0.75-1比例之間縮放
      float scaleFactor = MIN_SCALE
          + (1 - MIN_SCALE) * (1 - Math.abs(position));
      page.setScaleX(scaleFactor);
      page.setScaleY(scaleFactor);
    } else { // (1,+Infinity]
      // 頁(yè)面遠(yuǎn)離右側(cè)頁(yè)面
      page.setAlpha(0);
    }

  }
}

Github代碼地址

以上是一些ViewPager做引導(dǎo)頁(yè)做用的到一些知識(shí)點(diǎn),希望和大家分享共同學(xué)習(xí)。由于水平有限,有什么不對(duì)的地方歡迎指正。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

最新評(píng)論