博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义类似viewpager的viewgroup
阅读量:5734 次
发布时间:2019-06-18

本文共 10124 字,大约阅读时间需要 33 分钟。

  hot3.png

1.自定义控件

import android.content.Context;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.Log;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.Scroller;/** * Created by Administrator on 2019/2/26 */public class HorizontalScrollLayout extends ViewGroup {    /**     * 屏幕的宽度     */    private int mScreenWidth;    /**     * 手指按下时的getScrollX     */    private int mScrollStart;    /**     * 手指抬起时的getScrollX     */    private int mScrollEnd;    /**     * 记录移动时的X     */    private int mLastX;    /**     * 滚动的辅助类     */    private Scroller mScroller;    /**     * 是否正在滚动     */    private boolean isScrolling;    /**     * 加速度检测     */    private VelocityTracker mVelocityTracker;    /**     * 记录当前页     */    private int currentPage = 0;    /**     * 子控件个数     */    private int childCount = 0;    private OnPageChangeListener mOnPageChangeListener;//    public HorizontalScrollLayout(Context context) {//        super(context);//        init(context);//    }    public HorizontalScrollLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }//    public HorizontalScrollLayout(Context context, AttributeSet attrs, int defStyleAttr) {//        super(context, attrs, defStyleAttr);//        init(context);//    }    private void init(Context context) {        /**         * 获得屏幕的宽度         */        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics outMetrics = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics(outMetrics);        mScreenWidth = outMetrics.widthPixels;        //selectItem(0);        // 初始化        mScroller = new Scroller(context);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        //Log.i("order", "order:onMeasure");        childCount = getChildCount();        //Log.i("test", "onMeasure childCount = " + childCount);        for (int i = 0; i < childCount; ++i) {            View childView = getChildAt(i);            measureChild(childView, mScreenWidth, heightMeasureSpec);        }    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        //Log.i("order", "order:onLayout");        if (changed) {            //Log.i(HorizontalScrollLayout.class.getName(), "changed == true");            //int childCount = getChildCount();            //Log.i("test", "onLayout childCount = " + childCount);            // 设置主布局的高度            MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();            lp.width = mScreenWidth * childCount;            setLayoutParams(lp);            for (int i = 0; i < childCount; i++) {                View child = getChildAt(i);                if (child.getVisibility() != View.GONE) {                    child.layout(i * mScreenWidth, t, (i + 1) * mScreenWidth, b);// 调用每个自布局的layout                }            }        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        //Log.i("order", "order:onTouchEvent");        // 如果当前正在滚动,调用父类的onTouchEvent        if (isScrolling) {            //Log.i(HorizontalScrollLayout.class.getName(), "onTouchEvent isScrolling");            return super.onTouchEvent(event);        }        int action = event.getAction();        int x = (int) event.getX();        //Log.i(HorizontalScrollLayout.class.getName(), "onTouchEvent x = " + x);        obtainVelocity(event);        switch (action) {            case MotionEvent.ACTION_DOWN:                mScrollStart = getScrollX();                //Log.i("ScrollTag", "ACTION_DOWN mScrollStart = getScrollX() = " + mScrollStart);                mLastX = x;                //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_DOWN mLastX = " + mLastX);                break;            case MotionEvent.ACTION_MOVE:                if (!mScroller.isFinished()) {                    //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_MOVE !mScroller.isFinished()");                    mScroller.abortAnimation();                }                int dx = mLastX - x;//                //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_MOVE last dx = " + dx);                // 边界值检查                int scrollX = getScrollX();                // 已经到达左端,右拉多少,就往左滚动多少                if (dx < 0 && scrollX == 0) {                    //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_MOVE (dx < 0 && scrollX < 0), dx = " + dx + ", scrollX = " + scrollX);                    dx = 0;                }                // 已经到达右部,左拉多少,就往右滚动多少//                if (dx > 0 && scrollX + dx > getWidth() - mScreenWidth) {                //Log.i("test", "getWidth() = " + getWidth() + ", mScreenWidth = " + mScreenWidth);                if (dx > 0 && scrollX == mScreenWidth * (childCount -1)) {                    //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_MOVE (dx > 0 && scrollX > mScreenWidth * childCount), dx = " + dx + ", scrollX = " + scrollX + ", mScreenWidth * childCount = " + mScreenWidth * childCount);//                    dx = getWidth() - mScreenWidth - scrollX;                    dx = 0;                }                //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_MOVE dx = " + dx);                scrollBy(dx, 0);                mLastX = x;                //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_MOVE mLastX = " + mLastX);                break;            case MotionEvent.ACTION_UP:                mScrollEnd = getScrollX();                //Log.i("ScrollTag", "ACTION_UP mScrollEnd = getScrollX() = " + mScrollEnd);                int dScrollX = mScrollEnd - mScrollStart;                //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_UP dScrollX = " + dScrollX);                if (wantScrollToNext())// 往左滑动                {                    //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_UP wantScrollToNext");                    if (shouldScrollToNext()) {                        //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_UP shouldScrollToNext");                        mScroller.startScroll(getScrollX(), 0, mScreenWidth - dScrollX, 0);                    } else {                        //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_UP shouldScrollToNext false");                        mScroller.startScroll(getScrollX(), 0, -dScrollX, 0);                    }                }                if (wantScrollToPre())// 往右滑动                {                    //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_UP wantScrollToPre");                    if (shouldScrollToPre()) {                        //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_UP shouldScrollToPre");                        mScroller.startScroll(getScrollX(), 0, -mScreenWidth - dScrollX, 0);                    } else {                        //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_UP shouldScrollToPre false");                        mScroller.startScroll(getScrollX(), 0, -dScrollX, 0);                    }                }                isScrolling = true;                //Log.i(HorizontalScrollLayout.class.getName(), "ACTION_UP isScrolling = true");                postInvalidate();                recycleVelocity();                break;        }        return true;    }    /**     * 初始化加速度检测器     *     * @param event     */    private void obtainVelocity(MotionEvent event) {        if (mVelocityTracker == null) {            mVelocityTracker = VelocityTracker.obtain();        }        mVelocityTracker.addMovement(event);    }    /**     * 根据用户滑动,判断用户的意图是否是滚动到下一页     *     * @return     */    private boolean wantScrollToNext() {        return mScrollEnd > mScrollStart;    }    /**     * 根据滚动距离判断是否能够滚动到下一页     *     * @return     */    private boolean shouldScrollToNext() {        return mScrollEnd - mScrollStart > mScreenWidth / 2 || Math.abs(getVelocity()) > 600;    }    /**     * 根据用户滑动,判断用户的意图是否是滚动到上一页     *     * @return     */    private boolean wantScrollToPre() {        return mScrollEnd < mScrollStart;    }    /**     * 根据滚动距离判断是否能够滚动到上一页     *     * @return     */    private boolean shouldScrollToPre() {        return -mScrollEnd + mScrollStart > mScreenWidth / 2 || Math.abs(getVelocity()) > 600;    }    /**     * 获取x方向的加速度     *     * @return     */    private int getVelocity() {        mVelocityTracker.computeCurrentVelocity(1000);        return (int) mVelocityTracker.getXVelocity();    }    @Override    public void computeScroll() {        super.computeScroll();        if (mScroller.computeScrollOffset()) {            scrollTo(mScroller.getCurrX(), 0);            postInvalidate();        } else {            int position = getScrollX() / mScreenWidth;            //Log.i("xxx", position + "," + currentPage);            if (position != currentPage) {                if (mOnPageChangeListener != null) {                    currentPage = position;                    mOnPageChangeListener.onPageChange(currentPage);                }            }            isScrolling = false;            //Log.i(HorizontalScrollLayout.class.getName(), "computeScroll isScrolling = false");        }    }    /**     * 释放资源     */    private void recycleVelocity() {        if (mVelocityTracker != null) {            mVelocityTracker.recycle();            mVelocityTracker = null;        }    }    /**     * 设置回调接口     *     * @param onPageChangeListener     */    public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) {        mOnPageChangeListener = onPageChangeListener;    }    /**     * 回调接口     */    public interface OnPageChangeListener {        void onPageChange(int currentPage);    }    /**     * 设置选中某一页     */    public void selectItem(int index) {        scrollTo(index * mScreenWidth, 0);        invalidate();    }}

2.布局文件

 

转载于:https://my.oschina.net/glfei/blog/3016131

你可能感兴趣的文章
《远见》的读后感作文1000字范文
查看>>
重置密码、单用户模式、救援模式
查看>>
LAMP环境搭建1-mysql5.5
查看>>
第三课 Linux目录及文件管理、用户组管理及bash重定向
查看>>
shell 脚本攻略--小试牛刀
查看>>
spring boot view override
查看>>
bzoj 2282: [Sdoi2011]消防
查看>>
我的友情链接
查看>>
centos5.9使用RPM包搭建lamp平台
查看>>
关于C#面向对象2
查看>>
Javascript String类的属性及方法
查看>>
vim编辑器如何添加或删除多行注释
查看>>
[LeetCode] Merge Intervals
查看>>
iOS开发-按钮的基本使用
查看>>
在QT和SDL搭建的框架中使用OPENGL在SDL窗口上进行绘图
查看>>
REST技术第三步 @BeanParam的使用
查看>>
模板 读入挂!
查看>>
SharePoint 读取 Site Columns 的数据并绑定到DropdownList
查看>>
Python中的对象行为与特殊方法(二)类型检查与抽象基类
查看>>
使用 axios 详解
查看>>