Android HorizontalScrollView回弹效果

转载记录备份查阅

import android.annotation.SuppressLint;
import android.os.Build;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;

/**
 * Created by Sugar on 2017/12/7/0007.
 */

public class UITools {

    /**HorizontalScrollView添加阻尼效果
     * ScrollView效果不太好
     * 利用父元素的Padding给ScrollView添加弹性
     * @param scrollView
     * @param padding
     */
    public static void elasticPadding(final ScrollView scrollView, final int padding){
        View child = scrollView.getChildAt(0);
        //记录以前的padding
        final int oldpt = child.getPaddingTop();
        final int oldpb = child.getPaddingBottom();
        //设置新的padding
        child.setPadding(child.getPaddingLeft(), padding+oldpt, child.getPaddingRight(), padding+oldpb);

        //添加视图布局完成事件监听
        scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            private boolean inTouch = false; //手指是否按下状态

            @SuppressLint("NewApi")
            private void disableOverScroll(){
                scrollView.setOverScrollMode(ScrollView.OVER_SCROLL_NEVER);
            }

            /**  滚动到顶部 */
            private void scrollToTop(){
                scrollView.smoothScrollTo(scrollView.getScrollX(), padding-oldpt);
            }

            /** 滚动到底部 */
            private void scrollToBottom(){
                scrollView.smoothScrollTo(scrollView.getScrollX(), scrollView.getChildAt(0).getBottom()-scrollView.getMeasuredHeight()-padding+oldpb);
            }

            /** 检测scrollView结束以后,复原位置 */
            private final Runnable checkStopped = new Runnable() {
                @Override
                public void run() {
                    int y = scrollView.getScrollY();
                    int bottom = scrollView.getChildAt(0).getBottom()-y-scrollView.getMeasuredHeight();
                    if(y <= padding && !inTouch){
                        scrollToTop();
                    }else if(bottom<=padding && !inTouch){
                        scrollToBottom();
                    }
                }
            };

            @SuppressWarnings("deprecation")
            @Override
            public void onGlobalLayout() {
                //移除监听器
                scrollView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                //设置最小高度
                //scrollView.getChildAt(0).setMinimumHeight(scrollView.getMeasuredHeight());
                //取消overScroll效果
                if(Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD){
                    disableOverScroll();
                }

                scrollView.setOnTouchListener(new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_POINTER_DOWN){
                            inTouch = true;
                        }else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL){
                            inTouch = false;
                            //手指弹起以后检测一次是否需要复原位置
                            scrollView.post(checkStopped);
                        }
                        return false;
                    }
                });

                scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
                    @Override
                    public void onScrollChanged() {
                        if(!inTouch && scrollView!=null && scrollView.getHandler()!=null){//如果持续滚动,移除checkStopped,停止滚动以后只执行一次检测任务
                            scrollView.getHandler().removeCallbacks(checkStopped);
                            scrollView.postDelayed(checkStopped, 100);
                        }
                    }
                });

                //第一次加载视图,复原位置
                scrollView.postDelayed(checkStopped, 300);
            }
        });
    }

    /**
     * 利用父元素的Padding给HorizontalScrollView添加弹性
     * @param scrollView
     * @param padding
     */
    public static void elasticPadding(final HorizontalScrollView scrollView, final int padding){
        Log.i("", "elasticPadding>>>>!!");
        View child = scrollView.getChildAt(0);

        //记录以前的padding
        final int oldpt = child.getPaddingTop();
        final int oldpb = child.getPaddingBottom();
        //设置新的padding
        child.setPadding(padding+oldpt, child.getPaddingTop(), padding+oldpb, child.getPaddingBottom());

        //添加视图布局完成事件监听
        scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            private boolean inTouch = false; //手指是否按下状态

            @SuppressLint("NewApi")
            private void disableOverScroll(){
                scrollView.setOverScrollMode(ScrollView.OVER_SCROLL_NEVER);
            }

            /**  滚动到左边 */
            private void scrollToLeft(){
                scrollView.smoothScrollTo(padding-oldpt, scrollView.getScrollY());
            }

            /** 滚动到底部 */
            private void scrollToRight(){
                scrollView.smoothScrollTo(scrollView.getChildAt(0).getRight()-scrollView.getMeasuredWidth()-padding+oldpb, scrollView.getScrollY());
            }

            /** 检测scrollView结束以后,复原位置 */
            private final Runnable checkStopped = new Runnable() {
                @Override
                public void run() {
                    int x = scrollView.getScrollX();
                    int bottom = scrollView.getChildAt(0).getRight()-x-scrollView.getMeasuredWidth();
                    if(x <= padding && !inTouch){
                        scrollToLeft();
                    }else if(bottom<=padding && !inTouch){
                        scrollToRight();
                    }
                }
            };

            @SuppressWarnings("deprecation")
            @Override
            public void onGlobalLayout() {
                //移除监听器
                scrollView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

                //取消overScroll效果
                if(Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD){
                    disableOverScroll();
                }

                scrollView.setOnTouchListener(new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_POINTER_DOWN){
                            inTouch = true;
                        }else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL){
                            inTouch = false;
                            //手指弹起以后检测一次是否需要复原位置
                            scrollView.post(checkStopped);
                        }
                        return false;
                    }
                });

                scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
                    @Override
                    public void onScrollChanged() {
                        //如果持续滚动,移除checkStopped,停止滚动以后只执行一次检测任务
                        if(!inTouch && scrollView!=null && scrollView.getHandler()!=null){
                            scrollView.getHandler().removeCallbacks(checkStopped);
                            scrollView.postDelayed(checkStopped, 100);
                        }
                    }
                });

                //第一次加载视图,复原位置
                scrollView.postDelayed(checkStopped, 300);
            }
        });
    }
}
调用方式:

UITools.elasticPadding((HorizontalScrollView) findViewById(R.id.hs), 500);

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于动态加载数据并实现横向滑动效果HorizontalScrollView,你可以按照以下步骤进行操作: 1. 在你的布局文件中添加 HorizontalScrollView 控件: ```xml <HorizontalScrollView android:id="@+id/horizontalScrollView" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/linearLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <!-- 这里可以动态添加子视图 --> </LinearLayout> </HorizontalScrollView> ``` 2. 在你的代码中获取 HorizontalScrollView 和 LinearLayout 对象,并根据数据动态添加子视图: ```java HorizontalScrollView horizontalScrollView = findViewById(R.id.horizontalScrollView); LinearLayout linearLayout = findViewById(R.id.linearLayout); for (int i = 0; i < 数据集合.size(); i++) { final 数据类型 数据 = 数据集合.get(i); // 创建子视图 TextView textView = new TextView(this); textView.setText(数据.文本); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 处理单项点击事件 // 这里可以根据需要执行相应的操作 } }); // 将子视图添加到 LinearLayout linearLayout.addView(textView); } ``` 3. 如果你希望每次只能选择一项,你可以在点击事件中记录当前选中的项,并在下次点击时取消上一次的选中效果: ```java private TextView lastSelectedView; // ... textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (lastSelectedView != null) { // 取消上一次选中的效果 lastSelectedView.setSelected(false); } // 设置当前选中的效果 textView.setSelected(true); lastSelectedView = textView; // 处理单项点击事件 // 这里可以根据需要执行相应的操作 } }); ``` 这样,你就可以实现在 HorizontalScrollView 中动态加载数据,并且只能单项点击的效果了。希望对你有帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值