滚动以后内容自动居中的HorizontalScrollView

可以监听滚动状态的HorizontalScrollView

package com.trs.v7.home.view;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;

/**
 * 可以监听滚动状态的HorizontalScrollView
 */
public class WZHorizontalScrollView extends HorizontalScrollView {
    public WZHorizontalScrollView(Context context) {
        super(context);
    }

    public WZHorizontalScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public interface ScrollViewListener {

        void onScrollChanged(ScrollType scrollType);

    }

    private Handler mHandler;
    private ScrollViewListener scrollViewListener;
    //滚动状态:
    // IDLE 滚动停止  TOUCH_SCROLL 手指拖动滚动         FLING滚动
    public enum ScrollType{IDLE,TOUCH_SCROLL,FLING};

    /**
     * 记录当前滚动的距离
     */
    private int currentX = -9999999;
    /**
     * 当前滚动状态
     */
    private ScrollType scrollType = ScrollType.IDLE;
    /**
     * 滚动监听间隔
     */
    private int scrollDealy = 50;
    /**
     * 滚动监听runnable
     */
    private Runnable scrollRunnable = new Runnable() {

        @Override
        public void run() {
            // TODO Auto-generated method stub
            if(getScrollX()==currentX){
                //滚动停止  取消监听线程

                scrollType = ScrollType.IDLE;
                if(scrollViewListener!=null){
                    scrollViewListener.onScrollChanged(scrollType);
                }
                mHandler.removeCallbacks(this);
                return;
            }else{
                //手指离开屏幕    view还在滚动的时候
                scrollType = ScrollType.FLING;
                if(scrollViewListener!=null){
                    scrollViewListener.onScrollChanged(scrollType);
                }
            }
            currentX = getScrollX();
            mHandler.postDelayed(this, scrollDealy);
        }
    };


    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_MOVE:
                this.scrollType = ScrollType.TOUCH_SCROLL;
                scrollViewListener.onScrollChanged(scrollType);
                //手指在上面移动的时候   取消滚动监听线程
                mHandler.removeCallbacks(scrollRunnable);
                break;
            case MotionEvent.ACTION_UP:
                //手指移动的时候
                mHandler.post(scrollRunnable);
                break;
        }
        return super.onTouchEvent(ev);
    }

    /**
     * 必须先调用这个方法设置Handler  不然会出错
     *  2014-12-7 下午3:55:39
     * @author DZC
     * @return void
     * @param handler
     * @TODO
     */
    public void setHandler(Handler handler){
        this.mHandler = handler;
    }
    /**
     * 设置滚动监听
     *  2014-12-7 下午3:59:51
     * @author DZC
     * @return void
     * @param listener
     * @TODO
     */
    public void setOnScrollStateChangedListener(ScrollViewListener listener){
        this.scrollViewListener = listener;
    }

}

自动内容居中的HorizontalScrollView 继承自上一个HorizontalScrollView

package com.trs.v7.home.view;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/**
 * <pre>
 * Created by zhuguohui
 * Date: 2023/4/20
 * Time: 17:50
 * Desc:在滚动结束以后可以自动停留在居中位置的WZHorizontalScrollView
 * </pre>
 */
public class AutoCenterHorizontalScrollView extends WZHorizontalScrollView {
    public AutoCenterHorizontalScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setHandler(new Handler());
        setOnScrollStateChangedListener(scrollViewListener);
    }

    ScrollViewListener scrollViewListener = new ScrollViewListener() {
        @Override
        public void onScrollChanged(ScrollType scrollType) {

            if (scrollType == ScrollType.IDLE) {
                //滑动停止
                //判断是否是有内容
                int childCount = getChildCount();
                if (childCount == 0) {
                    return;
                }
                ViewGroup viewGroup = (ViewGroup) getChildAt(0);
                autoScroll(viewGroup);

            }
        }

        private void autoScroll(ViewGroup viewGroup) {
            View middleView = getMiddleView(viewGroup);
            //尝试将middleView显示在中央
            int targetX = middleView.getLeft() - ((getWidth() - middleView.getWidth()) / 2);
            //对targetX进行约束
            targetX = Math.max(targetX, 0);
            targetX = Math.min(viewGroup.getWidth() - getWidth(), targetX);
            int dx = targetX-getScrollX();
            smoothScrollBy(dx, 0);
        }

        private View getMiddleView(ViewGroup viewGroup) {
            //获取view中心点距离HorizontalScrollView中心点最近的view
            int hCenterX = getScrollX() + getWidth() / 2;
            View middleView = null;
            int minDistance = Integer.MAX_VALUE;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                View child = viewGroup.getChildAt(i);
                int vCenterX = child.getLeft() + child.getWidth() / 2;
                int distance = Math.abs(vCenterX - hCenterX);
                if (distance < minDistance) {
                    middleView = child;
                    minDistance = distance;
                }
            }

            return middleView;
        }

    };

}

和正常的HorizontalScrollView一样使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以通过两种方式实现这个功能: 1. 使用 `TabLayout` 的 `addOnTabSelectedListener` 方法,监听标签选中事件,在选中标签后,使用 `HorizontalScrollView` 的 `smoothScrollTo()` 方法将选中的标签滚动居中位置。 ```java TabLayout tabLayout = findViewById(R.id.tabLayout); HorizontalScrollView scrollView = findViewById(R.id.scrollView); tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { // 获取选中标签的索引 int position = tab.getPosition(); // 获取标签的宽度 int tabWidth = tabLayout.getTabAt(position).getCustomView().getWidth(); // 获取屏幕宽度 int screenWidth = getResources().getDisplayMetrics().widthPixels; // 计算要滚动的距离,使选中标签居中 int scrollDistance = (tabWidth - screenWidth) / 2; // 滚动到指定位置 scrollView.smoothScrollTo(scrollDistance, 0); } @Override public void onTabUnselected(TabLayout.Tab tab) { // Do nothing } @Override public void onTabReselected(TabLayout.Tab tab) { // Do nothing } }); ``` 2. 自定义 `TabLayout` 的样式,使其支持居中显示选中标签。您可以使用 `TabGravity.CENTER` 属性将标签居中显示。 在 XML 布局文件中,将 `TabLayout` 的 `tabGravity` 属性设置为 `center`: ```xml <com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabGravity="center" /> ``` 请注意,第二种方式只是将选中标签居中显示,并不会自动滚动居中位置。如果您需要在选中标签后进行滚动,仍然需要使用第一种方式中的代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值