先看一下我們要開發的界面(三張圖片,滑到最后一個會出現開始體驗的Button,下面的小紅點會跟著一起滑動):
首先看一下布局文件:
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:id="@+id/activity_guide" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 tools:context="com.coderwei.a71_zhbj.activity.GuideActivity"> 8 9 <android.support.v4.view.ViewPager 10 android:id="@+id/vp_guide" 11 android:layout_width="match_parent" 12 android:layout_height="match_parent" 13 /> 14 <Button 15 android:layout_centerHorizontal="true" 16 android:layout_alignParentBottom="true" 17 android:layout_marginBottom="70dp" 18 android:padding="10dp" 19 android:id="@+id/start_btn" 20 android:textColor="#f1eaea" 21 android:background="#e71616" 22 android:text="開始體驗" 23 android:visibility="invisible" 24 android:layout_width="wrap_content" 25 android:layout_height="wrap_content" /> 26 27 <RelativeLayout 28 android:layout_width="wrap_content" 29 android:layout_height="wrap_content" 30 android:layout_alignParentBottom="true" 31 android:layout_centerHorizontal="true" 32 android:layout_marginBottom="30dp"> 33 34 <LinearLayout 35 android:id="@+id/ll_container" 36 android:layout_width="wrap_content" 37 android:layout_height="wrap_content"> 38 39 </LinearLayout> 40 <ImageView 41 android:id="@+id/iv_red" 42 android:src="@drawable/shap_red" 43 android:layout_width="wrap_content" 44 android:layout_height="wrap_content" /> 45 46 </RelativeLayout> 47 48 </RelativeLayout>
然后就是代碼了:
1 public class GuideActivity extends Activity { 2 3 private ViewPager mViewPager; 4 private int[] mImageIds = new int[]{R.drawable.guide_1,R.drawable.guide_2,R.drawable.guide_3}; 5 private ArrayList<ImageView> mImageViewList; 6 private LinearLayout llContainer; 7 private ImageView ivRedPoint; 8 private int mPaintDis; 9 private Button start_btn; 10 11 @Override 12 protected void onCreate(Bundle savedInstanceState) { 13 super.onCreate(savedInstanceState); 14 requestWindowFeature(Window.FEATURE_NO_TITLE); 15 setContentView(R.layout.activity_guide); 16 mViewPager = (ViewPager)findViewById(R.id.vp_guide); 17 llContainer = (LinearLayout) findViewById(R.id.ll_container); 18 ivRedPoint = (ImageView) findViewById(R.id.iv_red); 19 start_btn = (Button) findViewById(R.id.start_btn); 20 initData(); 21 GuideAdapter adapter = new GuideAdapter(); 22 mViewPager.setAdapter(adapter); 23 24 //監聽布局是否已經完成 布局的位置是否已經確定 25 ivRedPoint.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 26 @Override 27 public void onGlobalLayout() { 28 //避免重復回調 出于兼容性考慮,使用了過時的方法 29 ivRedPoint.getViewTreeObserver().removeGlobalOnLayoutListener(this); 30 //布局完成了就獲取第一個小灰點和第二個之間left的距離 31 mPaintDis = llContainer.getChildAt(1).getLeft()-llContainer.getChildAt(0).getLeft(); 32 System.out.println("距離:"+mPaintDis); 33 } 34 }); 35 36 37 //ViewPager滑動Pager監聽 38 mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 39 //滑動過程中的回調 40 @Override 41 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 42 //當滑到第二個Pager的時候,positionOffset百分比會變成0,position會變成1,所以后面要加上position*mPaintDis 43 int letfMargin = (int)(mPaintDis*positionOffset)+position*mPaintDis; 44 //在父布局控件中設置他的leftMargin邊距 45 RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)ivRedPoint.getLayoutParams(); 46 params.leftMargin = letfMargin; 47 ivRedPoint.setLayoutParams(params); 48 } 49 50 51 @Override 52 public void onPageSelected(int position) { 53 System.out.println("position:"+position); 54 if (position==mImageViewList.size()-1){ 55 start_btn.setVisibility(View.VISIBLE); 56 } 57 58 } 59 60 @Override 61 public void onPageScrollStateChanged(int state) { 62 System.out.println("state:"+state); 63 } 64 }); 65 } 66 67 private void initData(){ 68 mImageViewList = new ArrayList<>(); 69 for (int i=0; i<mImageIds.length; i++){ 70 //創建ImageView把mImgaeViewIds放進去 71 ImageView view = new ImageView(this); 72 view.setBackgroundResource(mImageIds[i]); 73 //添加到ImageView的集合中 74 mImageViewList.add(view); 75 76 77 //小圓點 一個小灰點是一個ImageView 78 ImageView pointView = new ImageView(this); 79 pointView.setImageResource(R.drawable.shape); 80 //初始化布局參數,父控件是誰,就初始化誰的布局參數 81 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 82 if (i>0){ 83 //當添加的小圓點的個數超過一個的時候就設置當前小圓點的左邊距為10dp; 84 params.leftMargin=10; 85 } 86 //設置小灰點的寬高包裹內容 87 pointView.setLayoutParams(params); 88 //將小灰點添加到LinearLayout中 89 llContainer.addView(pointView); 90 } 91 } 92 93 94 class GuideAdapter extends PagerAdapter{ 95 96 //item的個數 97 @Override 98 public int getCount() { 99 return mImageViewList.size(); 100 } 101 102 @Override 103 public boolean isViewFromObject(View view, Object object) { 104 return view == object; 105 } 106 107 //初始化item布局 108 @Override 109 public Object instantiateItem(ViewGroup container, int position) { 110 ImageView view = mImageViewList.get(position); 111 container.addView(view); 112 return view; 113 } 114 115 //銷毀item 116 @Override 117 public void destroyItem(ViewGroup container, int position, Object object) { 118 container.removeView((View)object); 119 } 120 } 121 }
小灰點:
1 <?xml version="1.0" encoding="utf-8"?> 2 <shape 3 android:shape="oval" 4 xmlns:android="http://schemas.android.com/apk/res/android"> 5 <!--小灰點--> 6 <solid android:color="#cccccc"/> 7 <size android:width="10dp" android:height="10dp"/> 8 9 </shape>
小紅點:
1 <?xml version="1.0" encoding="utf-8"?> 2 <shape 3 android:shape="oval" 4 xmlns:android="http://schemas.android.com/apk/res/android"> 5 6 <solid android:color="#f00"/> 7 <size android:width="10dp" android:height="10dp"/> 8 </shape>
ViewPage都很簡單,上一個博文也詳細介紹了的,這里就不細說了,主要是下面的小紅點跟著Pager一起走。
上面其實是三個小灰點,然后小灰點的上面有一個小紅點,通過計算出第一個小灰點與第二個小灰點之間的距離,我們就可以用設置ViewPager的滑動監聽,然后讓小紅點跟著pager一起動(改變的是父控件中的內邊距)。
計算小灰點之間的距離時需要注意的是,必須等到布局位置確定下來的才能的到小灰點之間的距離(界面生成的過程 measure->layout(確定位置)->draw(activity的onCreate方法執行結束之后才會走此流程)),所以要設置layout的監聽:
ivRedPoint.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
然后的到小灰點之間的距離:
mPaintDis = llContainer.getChildAt(1).getLeft()-llContainer.getChildAt(0).getLeft();
需要注意的是這句代碼:
int letfMargin = (int)(mPaintDis*positionOffset)+position*mPaintDis;
positionOffset是當前滑動的百分比,當進入第二個page的時候,值為0,
position代表當前是第幾個page,從0開始,也就是說當我滑到第二個page的時候 mPaintDis*0+1*mPaintDis;
PS:思路總結:
1、頁面由 ViewPager + Button + RelativeLayout(LinearLayout + TextView)組成,
2、LinearLayout放的是小灰點,小灰點的個數由ViewPager的個數覺得,所以LinearLayout添加小灰點的時候是與VIewPager的圖片資源添加到集合是一起的。
3、然后小紅點就是一個TextView因為相對布局的原因,小紅點的初始位置會和小灰點的第一個點重合,
4、然后監聽ViewPager的滑動事件,通過計算第一個和第二個小灰點的左邊到LinearLayout的左邊的邊距差,來移動小紅點的位置,但是確定位置的查體須 是布局的位置已經確定,所以我們就要監聽布局是否已經確定,等確定后再去計算位置差。
文章列表