1. 程式人生 > >自定義橫向日期選擇器,可滑動,可點選

自定義橫向日期選擇器,可滑動,可點選

類似效果如下,可以點選日期,實現和下面的別的內容互動,點選左右按鈕可以切換頁面,同時可以左右滑動。
佈局檔案比較簡單,直接上程式碼:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <LinearLayout
android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" >
<Button android:id="@+id/btn_left" android:layout_width="24dp" android:layout_height="match_parent"
/>
<com.wscq.dataindicator.DataIndicatorView android:id="@+id/data_indicator" android:layout_width="0dp" android:layout_height="135dp" android:layout_weight="1" > </com.wscq.dataindicator.DataIndicatorView> <Button
android:id="@+id/btn_right" android:layout_width="24dp" android:layout_height="match_parent" />
</LinearLayout> <TextView android:id="@+id/tv_context" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/ll" android:gravity="center" android:textSize="30sp" /> </RelativeLayout>

其中主要的難度就是自定義了一個橫向的LinearLayout,其中因為只是攔截橫向滾動,所以需要有如下的事件分發程式碼:


    /** 事件分發,只攔截橫向滑動,不攔截其他事件 */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;
        int x = (int) ev.getX();
        int y = (int) ev.getY();

        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            intercepted = false;
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
                intercepted = true;
            }
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            int deltaX = x - mLastXIntercept;
            int deltaY = y - mLastYIntercept;
            // 判斷是不是橫向滑動
            if (Math.abs(deltaX) > Math.abs(deltaY)) {
                intercepted = true;
            } else {
                intercepted = false;
            }
            // 判斷是否是有效的滑動
            if (Math.abs(deltaX) < ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
                intercepted = false;
            }
            break;
        }
        case MotionEvent.ACTION_UP: {
            intercepted = false;
            break;
        }
        default:
            break;
        }
        mLastX = x;
        mLastY = y;
        mLastXIntercept = x;
        mLastYIntercept = y;
        return intercepted;
    }

    /** 橫向滑動時候的相關處理操作 */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mVelocityTracker.addMovement(event);
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
            }
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            // 獲取水平方向的移動距離
            int deltaX = x - mLastX;
            // 因為是水平移動,所以這個變數並沒有使用
            int deltaY = y - mLastY;
            // 移動到對應的地方
            scrollBy(-deltaX, 0);
            break;
        }
        case MotionEvent.ACTION_UP: {
            // 設定滾動時間
            mVelocityTracker.computeCurrentVelocity(1000);
            // 當水平距離大於某個值時候,移動到下一頁,否則停留在當前頁
            float xVelocity = mVelocityTracker.getXVelocity();
            int page = mChoosePage;
            if (Math.abs(xVelocity) >= mLayoutWidth / 3) {
                // 更新當前螢幕的頁數
                page = xVelocity > 0 ? page - 1 : page + 1;
            }
            scrollPage(page);
            mVelocityTracker.clear();
            break;
        }
        default:
            break;
        }
        // 更新最後觸控點的座標
        mLastX = x;
        mLastY = y;
        return true;
    }

這裡的橫向滑動是彈性滑動,實現彈性滑動需要有如下程式碼:

/**
 * 頁數改變時的滾動方法
 * 
 * @param page
 */
public void scrollPage(int page) {
    // 取到正確的page值
    mChoosePage = Math.max(0, Math.min(page, mPageSum));
    // 如果顯示的不是當前頁,重置所有文字顏色,防止view複用引發的字型顏色顯示異常
    if (mChooseIndex / 7 == mChoosePage) {
        highLightTextView(mChooseIndex);
    } else {
        resetTextViewColor();
    }

    // 滾動到對應的位置
    int scrollX = getScrollX();
    int delta = mChoosePage * mLayoutWidth - scrollX;
    mScroller.startScroll(scrollX, 0, delta, 0, 1000);
    invalidate();

    // 回撥頁面改變監聽
    if (null != listener) {
        listener.onPageChangedListener(mChoosePage);
    }
}

/** 覆寫方法,用來實現彈性滑動 */
@Override
public void computeScroll() {
    super.computeScroll();
    if (mScroller.computeScrollOffset()) {
        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
        postInvalidate();
    }
}

“`