【安卓自定義控制元件】自定義ViewGroup實現透明背景的ViewPager效果
阿新 • • 發佈:2019-01-08
HelloWorld!
作為一名屌絲程式設計師,在部落格園寫第一篇技術部落格內心是無比激動滴,其實作為一名忙成狗的Android開發人員,一直覺得自己永遠都不會有時間去寫部落格,
因為我TM連找女朋友的時間都沒用==
言歸正傳,今天自定義控制元件系列要實現的效果是自定義ViewGroup來實現ViewPager的效果,並且自帶美女背景喲~
廢話不多少,上佈局程式碼:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="#ffffff" android:layout_gravity="center" android:layout_width="match_parent" android:layout_height="match_parent"><com.example.myview.HorizontalScrollViewGroup android:layout_width="match_parent" android:background="@drawable/mn" android:layout_height="match_parent"> <TextView android:layout_width="match_parent"android:layout_height="match_parent" android:background="#ccee342a" android:textSize="20sp" android:textColor="#000000" android:gravity="center" android:text="First Page"/> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ccadee40" android:textSize="20sp" android:textColor="#000000" android:gravity="center" android:text="Second Page"/> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:background="#cc347cee" android:textSize="20sp" android:textColor="#000000" android:gravity="center" android:text="Third Page"/> </com.example.myview.HorizontalScrollViewGroup> </RelativeLayout>
佈局檔案很簡單,就是把自定義的HorizontalScrollViewGroup放進去
佈局中設定了HorizontalScrollViewGroup的背景圖片,這個大家隨意設定,圖片就不傳上去了。
HorizontalScrollViewGroup的程式碼如下:
package com.example.myview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewGroup; import android.widget.Scroller; /** * Created by WangChunLei on 15/10/29. * 橫向移動的佈局物件,類似於ViewPager的效果 */ public class HorizontalScrollViewGroup extends ViewGroup { private static final String TAG = "HorizontalScrollView"; /*佈局的寬度*/ private int mScreenWidth; /*佈局高度*/ private int mScreenHeight; int mLastX = 0; private int x; /*子View的個數*/ private int mChildCount; /*ACTION_DOWN記錄的手指座標*/ private int mDownX; private Scroller mScroller; private VelocityTracker mVelocityTracker; public HorizontalScrollViewGroup(Context context) { this(context, null); } public HorizontalScrollViewGroup(Context context, AttributeSet attrs) { this(context, attrs, 0); } public HorizontalScrollViewGroup(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context) { mScroller = new Scroller(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mScreenWidth = MeasureSpec.getSize(widthMeasureSpec); mScreenHeight = MeasureSpec.getSize(heightMeasureSpec); mChildCount = getChildCount(); measureChildren(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { Log.e(TAG, "onLayout====="); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); child.layout(i * mScreenWidth, 0, (i + 1) * mScreenWidth, mScreenHeight); } } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); mVelocityTracker = VelocityTracker.obtain(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mVelocityTracker != null) { mVelocityTracker.recycle(); } } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), 0); postInvalidate(); } } @Override public boolean onTouchEvent(MotionEvent event) { x = (int) event.getX(); mVelocityTracker.addMovement(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (!mScroller.isFinished()) { return false; } mDownX = getScrollX(); mLastX = x; break; case MotionEvent.ACTION_MOVE: int dx = x - mLastX; float scrollX = getScrollX(); if (scrollX - dx <= 0) { scrollTo(0, 0); } else if (scrollX - dx >= (mChildCount - 1) * mScreenWidth) { scrollTo((mChildCount - 1) * mScreenWidth, 0); } else { scrollBy(-dx, 0); } mLastX = x; break; case MotionEvent.ACTION_UP: int dScrollX = Math.abs(getScrollX() - mDownX); if (mDownX - getScrollX() > 0) {//右劃 if (mDownX - getScrollX() > mScreenWidth / 2 || getXVelocity() > 600) {//下一頁 mScroller.startScroll(getScrollX(), 0, dScrollX - mScreenWidth, 0); } else {//當前頁 mScroller.startScroll(getScrollX(), 0, dScrollX, 0); } } else if (getScrollX() - mDownX > 0) {//左劃 if (getScrollX() - mDownX > mScreenWidth / 2 || getXVelocity() > 600) {//上一頁 mScroller.startScroll(getScrollX(), 0, mScreenWidth - dScrollX, 0); } else {//當前頁 mScroller.startScroll(getScrollX(), 0, -dScrollX, 0); } } postInvalidate(); break; default: break; } return true; } private int getXVelocity() { mVelocityTracker.computeCurrentVelocity(1000); int xVelocity = (int) Math.abs(mVelocityTracker.getXVelocity()); return xVelocity; } }
按照自定義控制元件的步驟,
1.新建HorizontalScrollViewGroup類並繼承ViewGroup類,表問我為啥是ViewGroup而不是View,因為ViewGroup
才能包含其他的View物件
2.重寫onMeasure方法,設定HorizontalScrollViewGroup的寬高和子View的寬高
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mScreenWidth = MeasureSpec.getSize(widthMeasureSpec); mScreenHeight = MeasureSpec.getSize(heightMeasureSpec); mChildCount = getChildCount(); measureChildren(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); }
這裡通過measureChildren方法,直接把父ViewGroup的尺寸傳遞給了所有子View,因為每個View的尺寸都是跟父ViewGroup一樣的填充佈局。
3.onLayout中設定父ViewGroup的顯示範圍
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { Log.e(TAG, "onLayout====="); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); child.layout(i * mScreenWidth, 0, (i + 1) * mScreenWidth, mScreenHeight); } }
4.最後,在onTouchEvent方法中處理觸控事件
不說了,老闆來了,寫不下去了==