1. 程式人生 > >【安卓自定義控制元件】自定義ViewGroup實現透明背景的ViewPager效果

【安卓自定義控制元件】自定義ViewGroup實現透明背景的ViewPager效果

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方法中處理觸控事件
不說了,老闆來了,寫不下去了==