Android用戶引導頁實現,圓點實現動畫效果


當前市面上比較流行的應用,用戶引導頁已經是一個必不可缺的功能點了,簡單的介紹下應用的基礎功能或者版本升級功能點介紹。

那么常用的用戶引導頁是如何實現的呢?這篇文章就說說我個人用到的,並且覺得使用不錯的效果。

1、首先定義布局文件guide_layout.xml文件,主要使用ViewPager做頁面顯示,使用一個圓點布局顯示圓點,圓點根據圖片數目動態添加。

guide_layout.xml文件的代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/start_bg">
    
    <android.support.v4.view.ViewPager
        android:id="@+id/vp_guide" 
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <Button
        android:id="@+id/btn_skip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="30dp"
        android:text="跳過"
        android:textSize="16sp"
        android:padding="10dp"
        android:background="@color/light_gray"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"/>
    
    <Button 
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="invisible"
        android:text="開始使用"
        android:textSize="16sp"
        android:padding="10dp"
        android:background="@color/light_gray"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="60dp"/>
        
    <RelativeLayout 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="30dp">
        
        <!-- 線性布局用來顯示引導頁的圓點,使用代碼給布局中添加圓點 -->
        <LinearLayout 
            android:id="@+id/ll_point_group"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            
        </LinearLayout>
        
        <!-- 表示當前顯示的引導頁,覆蓋在待選中的圓點之上,寬高要注意保持一致 -->
        <View 
            android:id="@+id/view_guide_point"
            android:layout_width="12dp"
            android:layout_height="12dp"
            android:background="@drawable/shape_point_white"/>
        
    </RelativeLayout>
    
</RelativeLayout>

2、使用android中shape屬性,定義圓點的背景資源。
shape_point_gray.xml的代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval" >

    <solid android:color="@android:color/white" />

</shape>
3、activity文件中,定義引導頁加載的圖片數組,根據數組的長度動態添加知識圓點。

根據引導頁圖片數組長度,動態給指示圓點的父布局(線性布局)添加圓點控件,注意圓點的像素與移動圓點的像素一致。
核心代碼也很簡單,如下代碼塊即可實現:
  for (int i = 0; i < mImageIds.length; i++) {
         Log.d("Point View", "第" + i + "個圓點");
         View point = new View(this);
//       設置引導頁默認圓點背景
         point.setBackgroundResource(R.drawable.shape_point_gray);

         LayoutParams params = new LayoutParams(DensityUtils.dp2px(this, 12), DensityUtils.dp2px(this, 12));
         if(i > 0){
            params.leftMargin = DensityUtils.dp2px(this, 10); //從第二個圓點開始設置左間距
         }
         point.setLayoutParams(params);

         llPointGroup.addView(point); //將圓點添加到線性布局中
      }
還需要注意一個點,需要測繪切換頁面圓點移動的距離,其實就是兩個圓點左邊界之間的像素差,也就是切換頁面時圓點需要移動的像素值。
這里是把測繪過程放在所有圓點添加完成,圓點的父布局完成了布局樹的測量之后計算,代碼如下:
// 獲取視圖樹, 對layout繪制結束事件進行監聽
      llPointGroup.getViewTreeObserver().addOnGlobalLayoutListener(
            new OnGlobalLayoutListener() {

               public void onGlobalLayout() {
                  Log.d("llPointLayout", "llPointLayout繪制結束!");
                  llPointGroup.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                  if(mPointWidth == 0){
                     mPointWidth = llPointGroup.getChildAt(1).getLeft()
                           - llPointGroup.getChildAt(0).getLeft();
                     Log.d("圓點需要移動的距離:", mPointWidth + "");
                  }
               }
            });

然后就是在viewpager的適配器中,重寫onPageScrolled方法,就是在移動過程中,不斷地給選中圓點設置左邊界值,達到一個選中圓點動畫效果。

實現代碼塊如下:

/**
       * position : 當前的位置
       * positionOffset :    位置移動的百分比
       * positionOffsetPixels:   位置移動的px像素點
       */
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
         int len = (int) (mPointWidth * positionOffset + position * mPointWidth);
         RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) guidePoint.getLayoutParams();
         params.leftMargin = len; //設置選中圓點在父控件中的左間距

         guidePoint.setLayoutParams(params);       //重新給選中圓點設置布局參數
      }

完整的GuideActivity代碼如下:
package com.study.tracy.activity;

      import android.content.Intent;
      import android.support.v4.view.ViewPager;
      import android.support.v4.view.ViewPager.OnPageChangeListener;
      import android.util.Log;
      import android.view.View;
      import android.view.View.OnClickListener;
      import android.view.ViewTreeObserver.OnGlobalLayoutListener;
      import android.widget.Button;
      import android.widget.ImageView;
      import android.widget.LinearLayout;
      import android.widget.LinearLayout.LayoutParams;
      import android.widget.RelativeLayout;
      import com.study.tracy.R;
      import com.study.tracy.adapter.GuideAdapter;
      import com.study.tracy.base.BaseActivity;
      import com.study.tracy.constants.FlagConstants;
      import com.study.tracy.utils.DensityUtils;
      import com.study.tracy.utils.SharedPrefUtils;
      import java.util.ArrayList;

public class GuideActivity extends BaseActivity {

   private ViewPager vpGuide;

   private LinearLayout llPointGroup;     //引導圓點的父控件

   private View guidePoint;   //選中的圓點

   private Button startBtn;   //開始體驗按鈕

   private Button skipBtn;    //跳過按鈕

   // 引導頁背景圖片的id數組
   private static final int[] mImageIds = new int[] {R.mipmap.user_guide01,
         R.mipmap.user_guide02, R.mipmap.user_guide03 , R.mipmap.user_guide04, R.mipmap.user_guide05};
   private int mPointWidth = 0;// 圓點間的距離
   private ArrayList<ImageView> mImageViewList;

   private String from;

   @Override
   public void initViews() {
      this.setContentView(R.layout.guide_layout);
//    獲取從哪里進來的入口
      from = getIntent().getStringExtra("from");

      vpGuide = (ViewPager) findViewById(R.id.vp_guide);
      llPointGroup = (LinearLayout) findViewById(R.id.ll_point_group);
      guidePoint = findViewById(R.id.view_guide_point);
      startBtn = (Button) findViewById(R.id.btn_start);
      skipBtn = (Button) findViewById(R.id.btn_skip);
   }


   @Override
   public void initDatas() {
      BaseActivity.isOpenDistanceBack = false;
      mImageViewList = new ArrayList<ImageView>();

//    初始化引導頁的三個頁面
      ImageView imageView = null;
      for (int i = 0; i < mImageIds.length; i++) {
         imageView = new ImageView(this);
         imageView.setBackgroundResource(mImageIds[i]); // 設置引導頁的背景圖片
         mImageViewList.add(imageView);
      }

      for (int i = 0; i < mImageIds.length; i++) {
         Log.d("Point View", "第" + i + "個圓點");
         View point = new View(this);
//       設置引導頁默認圓點背景
         point.setBackgroundResource(R.drawable.shape_point_gray);

         LayoutParams params = new LayoutParams(DensityUtils.dp2px(this, 12), DensityUtils.dp2px(this, 12));
         if(i > 0){
            params.leftMargin = DensityUtils.dp2px(this, 10); //從第二個圓點開始設置左間距
         }
         point.setLayoutParams(params);

         llPointGroup.addView(point); //將圓點添加到線性布局中
      }

      // 獲取視圖樹, 對layout繪制結束事件進行監聽
      llPointGroup.getViewTreeObserver().addOnGlobalLayoutListener(
            new OnGlobalLayoutListener() {

               public void onGlobalLayout() {
                  Log.d("llPointLayout", "llPointLayout繪制結束!");
                  llPointGroup.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                  if(mPointWidth == 0){
                     mPointWidth = llPointGroup.getChildAt(1).getLeft()
                           - llPointGroup.getChildAt(0).getLeft();
                     Log.d("圓點需要移動的距離:", mPointWidth + "");
                  }
               }
            });

   }

   @Override
   public void initListeners() {
      vpGuide.setAdapter(new GuideAdapter(mImageViewList));
      vpGuide.setOnPageChangeListener(new GuidePageListener());
      startBtn.setOnClickListener(new OnClickListener() {
         public void onClick(View v) {
            skipToActivity();
         }
      });

      skipBtn.setOnClickListener(new OnClickListener() {
         public void onClick(View v) {
            skipToActivity();
         }
      });

   }

   private void skipToActivity() {
      // 更新引導頁是否顯示為true,下次進入就不顯示
      SharedPrefUtils.getInstance().setBoolean(FlagConstants.USER_GUIDE, true);

      // 跳轉到登錄的Activity中
      Intent intent = null;
//    if("setting".equals(from)){
//       intent = new Intent(GuideActivity.this, SettingActivity.class);
//    }else {
      intent = new Intent(GuideActivity.this, LoginActivity.class);
//    }
      startActivity(intent);
      finish();
   }


   class GuidePageListener implements OnPageChangeListener {

      // 滑動狀態發生變化
      public void onPageScrollStateChanged(int arg0) {}

      /**
       * position : 當前的位置
       * positionOffset :    位置移動的百分比
       * positionOffsetPixels:   位置移動的px像素點
       */
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
         int len = (int) (mPointWidth * positionOffset + position * mPointWidth);
         RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) guidePoint.getLayoutParams();
         params.leftMargin = len; //設置選中圓點在父控件中的左間距

         guidePoint.setLayoutParams(params);       //重新給選中圓點設置布局參數
      }

      public void onPageSelected(int position) {
         if(position == mImageIds.length - 1){
//          最后一個頁面,設置開始體驗按鈕顯示
            startBtn.setVisibility(View.VISIBLE);
         }else{
            startBtn.setVisibility(View.INVISIBLE);
         }
      }

   }

}
4、viewpager的適配器adapter,給每個pager頁面添加對應位置的圖片資源
package com.study.tracy.adapter;

import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import java.util.ArrayList;

public class GuideAdapter extends PagerAdapter {

   private ArrayList<ImageView> mImageViewList;
   
   public GuideAdapter(ArrayList<ImageView> mImageViewList) {
      this.mImageViewList = mImageViewList;
   }

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

   @Override
   public boolean isViewFromObject(View view, Object object) {
      return view == object;
   }
   
   @Override
   public void destroyItem(ViewGroup container, int position, Object object) {
      container.removeView((View)object);
   }
   
   @Override
   public Object instantiateItem(ViewGroup container, int position) {
      container.addView(mImageViewList.get(position));
      return mImageViewList.get(position);
   }

}
 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM