仿大众点评店铺详情的上下滚动、横向tab联动,标题滑动悬停到顶部,点击tab滚动到相应模块

先看效果图

   


实现思路:1. 重写 ScrollView ,添加滑动监听,2. 根据控件的坐标实现精确滑动。注释写的比较详细,直接上代码


/**
 * Created by John on 2017/10/31.
 *
 * 重写带有滑动监听的 ScrollView
 */
public class MyScrollView extends ScrollView {
    private ScrollViewListener scrollViewListener = null;
    private OnScrollViewTouchDown onScrollViewTouchDown = null;
    private int handlerWhatId = 65984;
    private int timeInterval = 20;
    private int lastY = 0;

    @SuppressLint("HandlerLeak")
    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == handlerWhatId) {
                if (lastY == getScrollY()) {
                    if (scrollViewListener != null) {
                        scrollViewListener.onScrollStop(true);
                    }
                } else {
                    if (scrollViewListener != null) {
                        scrollViewListener.onScrollStop(false);
                    }
                    handler.sendMessageDelayed(handler.obtainMessage(handlerWhatId, this), timeInterval);
                    lastY = getScrollY();
                }
            }
        }
    };

    public MyScrollView(Context context) {
        super(context);
    }

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 滚动监听
     */
    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

    /**
     * 自定义 ScrollView 滑动监听
     */
    public interface ScrollViewListener {
        /**
         * 滑动监听
         *
         * @param scrollView ScrollView控件
         * @param x          x轴坐标
         * @param y          y轴坐标
         * @param oldx       上一个x轴坐标
         * @param oldy       上一个y轴坐标
         */
        void onScrollChanged(ScrollView scrollView, int x, int y, int oldx, int oldy);

        /**
         * 是否滑动停止
         *
         * @param isScrollStop true:滑动停止;false:未滑动停止
         */
        void onScrollStop(boolean isScrollStop);
    }

    /**
     * 按下监听
     */
    public void setOnScrollViewTouchDown(OnScrollViewTouchDown onScrollViewTouchDown) {
        this.onScrollViewTouchDown = onScrollViewTouchDown;
    }

    /**
     * 自定义 ScrollView 触摸监听
     */
    public interface OnScrollViewTouchDown {
        /**
         * 按下监听
         *
         * @param isTouchDown 是否按下
         */
        void onTouchDown(boolean isTouchDown);
    }

    @Override
    protected void onScrollChanged(int x, int y, int oldx, int oldy) {
        super.onScrollChanged(x, y, oldx, oldy);
        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_UP) {
            handler.sendMessageDelayed(handler.obtainMessage(handlerWhatId, this), timeInterval);
            if (onScrollViewTouchDown != null) {
                onScrollViewTouchDown.onTouchDown(true);
            }
        }
        return super.onTouchEvent(ev);
    }
}


/**
 * Created by John on 2017/10/31.
 * <p>
 * 上下滑动标题联动、标题栏固定到顶部 效果
 */
public class MainActivity extends Activity implements View.OnClickListener {
    // 滑动 scrollview
    private MyScrollView my_scrollview;
    // 固定标题和滑动标题 LinearLayout
    private LinearLayout ll_title_in_scrollview, ll_title_top;
    // 固定标题
    private TextView tv_title1, tv_title2, tv_title3;
    // ScrollView 中的标题
    private TextView tv_title_in_scrollview1, tv_title_in_scrollview2, tv_title_in_scrollview3;

    // top界面、3body界面
    private LinearLayout ll_top_view, ll_body1, ll_body2, ll_body3;
    // 动画图片
    private ImageView imgv_cursor;
    // 动画图片偏移量
    private int offset = 0;
    // 上一个界面 id
    private int lastTabIndex = 0;
    /**
     * 用于在同一个内容模块内滑动,锁定导航标签,防止重复刷新标签
     * true: 锁定
     * false ; 没有锁定
     */
    private boolean content2NavigateFlagInnerLock = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initImageView();
        addClickListener();
        addScrollListener();
    }

    /**
     * 初始化界面控件
     */
    private void initView() {
        ll_title_in_scrollview = findViewById(R.id.ll_title_in_scrollview);
        ll_title_top = findViewById(R.id.ll_title_top);
        tv_title1 = findViewById(R.id.tv_title1);
        tv_title2 = findViewById(R.id.tv_title2);
        tv_title3 = findViewById(R.id.tv_title3);
        tv_title_in_scrollview1 = findViewById(R.id.tv_title_in_scrollview1);
        tv_title_in_scrollview2 = findViewById(R.id.tv_title_in_scrollview2);
        tv_title_in_scrollview3 = findViewById(R.id.tv_title_in_scrollview3);

        imgv_cursor = findViewById(R.id.imgv_cursor);

        my_scrollview = findViewById(R.id.my_scrollview);

        ll_top_view = findViewById(R.id.ll_top_view);
        ll_body1 = findViewById(R.id.ll_body1);
        ll_body2 = findViewById(R.id.ll_body2);
        ll_body3 = findViewById(R.id.ll_body3);
    }

    /**
     * 初始化滑动条
     */
    private void initImageView() {
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int screenW = dm.widthPixels;// 获取分辨率宽度
        offset = screenW / 3;// 计算偏移量
        LinearLayout.LayoutParams ll = new LinearLayout.LayoutParams(offset, 4);
        imgv_cursor.setLayoutParams(ll);
        Matrix matrix = new Matrix();
        matrix.postTranslate(offset, 0);
        imgv_cursor.setImageMatrix(matrix);// 设置动画初始位置
    }

    /**
     * 添加标题点击监听
     */
    private void addClickListener() {
        tv_title1.setOnClickListener(this);
        tv_title2.setOnClickListener(this);
        tv_title3.setOnClickListener(this);
        tv_title_in_scrollview1.setOnClickListener(this);
        tv_title_in_scrollview2.setOnClickListener(this);
        tv_title_in_scrollview3.setOnClickListener(this);
    }

    /**
     * 添加滑动监听
     */
    private void addScrollListener() {
        my_scrollview.setScrollViewListener(new MyScrollView.ScrollViewListener() {
            @Override
            public void onScrollChanged(ScrollView scrollView, int x, int y, int oldx, int oldy) {
                scrollRefreshNavigationTag(scrollView);
            }

            @Override
            public void onScrollStop(boolean isScrollStop) {
            }
        });
    }

    /**
     * 内容区域滑动刷新导航标签
     *
     * @param scrollView 内容模块容器
     */
    private void scrollRefreshNavigationTag(ScrollView scrollView) {
        if (scrollView == null) {
            return;
        }
        // 获得ScrollView滑动距离
        int scrollY = scrollView.getScrollY();

        // 确定头部标题显示或隐藏
        if (scrollY >= ll_title_in_scrollview.getTop()) {
            ll_title_top.setVisibility(View.VISIBLE);
        } else {
            ll_title_top.setVisibility(View.GONE);
        }

        // 确定ScrollView当前展示的顶部内容属于哪个内容模块
        if (scrollY >= ll_body3.getTop() - ll_title_in_scrollview.getHeight()) {
            refreshContent2NavigationFlag(2);
        } else if (scrollY >= ll_body2.getTop() - ll_title_in_scrollview.getHeight()) {
            refreshContent2NavigationFlag(1);
        } else if (scrollY >= ll_body1.getTop() - ll_title_in_scrollview.getHeight()) {
            refreshContent2NavigationFlag(0);
        }
    }

    /**
     * 刷新标签
     *
     * @param currentTagIndex 当前模块位置
     */
    private void refreshContent2NavigationFlag(int currentTagIndex) {
        // 上一个位置与当前位置不一致是,解锁内部锁,是导航可以发生变化
        if (lastTabIndex != currentTagIndex) {
            content2NavigateFlagInnerLock = false;
        }
        if (!content2NavigateFlagInnerLock) {
            // 锁定内部锁
            content2NavigateFlagInnerLock = true;
           // 滑动到指定位置
            splippingToTab(currentTagIndex);
        }
        lastTabIndex = currentTagIndex;
    }

    /**
     * 滑动到指定的位置
     *
     * @param tabIndex
     */
    private void splippingToTab(int tabIndex) {
        Animation animation = new TranslateAnimation(offset * lastTabIndex, offset * tabIndex, 0, 0);
        animation.setFillAfter(true);// True:图片停在动画结束位置
        animation.setDuration(200);
        imgv_cursor.startAnimation(animation);

        restoreStyle();
        if (tabIndex == 0) {
            setStyle(tv_title1);
        } else if (tabIndex == 1) {
            setStyle(tv_title2);
        } else if (tabIndex == 2) {
            setStyle(tv_title3);
        }
    }

    /**
     * 还原字体默认颜色
     */
    private void restoreStyle() {
        tv_title1.setTextColor(getResources().getColor(R.color.new_grey1));
        tv_title2.setTextColor(getResources().getColor(R.color.new_grey1));
        tv_title3.setTextColor(getResources().getColor(R.color.new_grey1));
    }

    /**
     * 设置选中字体颜色
     */
    private void setStyle(TextView txt) {
        txt.setTextColor(getResources().getColor(R.color.new_purple));
    }

    /**
     * 点击事件
     */
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv_title1: // 顶部标题
                my_scrollview.smoothScrollTo(0, ll_body1.getTop() - ll_title_in_scrollview.getHeight());
                break;
            case R.id.tv_title2:
                my_scrollview.smoothScrollTo(0, ll_body2.getTop() - ll_title_in_scrollview.getHeight());
                break;
            case R.id.tv_title3:
                my_scrollview.smoothScrollTo(0, ll_body3.getTop() - ll_title_in_scrollview.getHeight());
                break;
            case R.id.tv_title_in_scrollview1: // 滑动标题
                my_scrollview.smoothScrollTo(0, ll_body1.getTop() - ll_title_in_scrollview.getHeight());
                break;
            case R.id.tv_title_in_scrollview2:
                my_scrollview.smoothScrollTo(0, ll_body2.getTop() - ll_title_in_scrollview.getHeight());
                break;
            case R.id.tv_title_in_scrollview3:
                my_scrollview.smoothScrollTo(0, ll_body3.getTop() - ll_title_in_scrollview.getHeight());
                break;
        }
    }

}

本人抛砖引玉,希望大家能有更好的实现思路


demo 下载地址: http://download.csdn.net/download/qiushuiduren/10172007

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值