自定义横向日期选择器,可滑动,可点击

类似效果如下,可以点击日期,实现和下面的别的内容互动,点击左右按钮可以切换页面,同时可以左右滑动。
布局文件比较简单,直接上代码:

<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();
    }
}

“`

具体的代码可以参考如下地址:
https://github.com/h55l55/DateIndicator

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值