如何在Android中创建可反弹的滚动视图?

10

如何在Android上创建类似于iPhone的反弹ScrollView

4个回答

22

在Android的ScrollView中添加“bounce”效果

步骤1:在包com.base.view中创建新文件BounceScrollView

public class BounceScrollView extends ScrollView
{
    private static final int MAX_Y_OVERSCROLL_DISTANCE = 200;

    private Context mContext;
    private int mMaxYOverscrollDistance;

    public BounceScrollView(Context context) 
    {
        super(context);
        mContext = context;
        initBounceScrollView();
    }

    public BounceScrollView(Context context, AttributeSet attrs) 
    {
        super(context, attrs);
        mContext = context;
        initBounceScrollView();
    }

    public BounceScrollView(Context context, AttributeSet attrs, int defStyle) 
    {
        super(context, attrs, defStyle);
        mContext = context;
        initBounceScrollView();
    }

    private void initBounceScrollView()
    {
        //get the density of the screen and do some maths with it on the max overscroll distance
        //variable so that you get similar behaviors no matter what the screen size

        final DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
            final float density = metrics.density;

        mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE);
    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) 
    { 
        //This is where the magic happens, we have replaced the incoming maxOverScrollY with our own custom variable mMaxYOverscrollDistance; 
        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxYOverscrollDistance, isTouchEvent);  
    }

}

步骤2:在您的布局中,请更改

<ScrollView 
   android:id="@+id/list"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
/>
<com.base.view.BounceScrollView 
   android:id="@+id/list"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
/>

1
嗨,感谢您的解决方案,对我非常有效。请更新您的代码,在initBounceListView()中有一个小错误,应该是initBounceScrollView() ;) - Mario Fraiß
@Thien 谢谢你的解决方案。你知道我们如何在这个bouncescrollview中添加页眉和页脚吗? - Anu
如果滚动视图中的内容少于滚动视图的高度,有没有办法实现反弹效果? - Artur Movsesyan
1
@ArturMovsesyan 在 ScrollView 中使用 android:overScrollMode="always" 设置。 - sidon
1
但是在缓慢滚动时,这并不顺畅。当缓慢地向上或向下拉时,会在某些点上卡住。 - Shadow
显示剩余4条评论

5

我有这个回答的改进版本:https://dev59.com/ZWs05IYBdhLWcg3wD90B#13391248。 所以我的版本是(HorizontalScrollView的示例):

public class HorizontalOverScrollView extends HorizontalScrollView {
    private static final int WIDTH_DEVIDER_OVERSCROLL_DISTANCE = 3;

    private TimeInterpolator mInterpolator;
    private int mMaxOverscrollDistance;
    private int mAnimTime;
    private long mStartTime;

    /**
     * Instantiates {@link HorizontalOverScrollView} object.
     */
    public HorizontalOverScrollView(final Context context) {
        super(context);
        init();
    }

    /**
     * Instantiates {@link HorizontalOverScrollView} object.
     */
    public HorizontalOverScrollView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * Instantiates {@link HorizontalOverScrollView} object.
     */
    public HorizontalOverScrollView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        final int widthPixels = getContext().getResources().getDisplayMetrics().widthPixels;
        mMaxOverscrollDistance = widthPixels / WIDTH_DEVIDER_OVERSCROLL_DISTANCE;
        mAnimTime = getContext().getResources().getInteger(android.R.integer.config_mediumAnimTime);
        mInterpolator = new DecelerateInterpolator();
    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
        int overScrollDistance = mMaxOverscrollDistance;
        if (isTouchEvent) {
            mStartTime = AnimationUtils.currentAnimationTimeMillis();
        } else {
            final long elapsedTime = AnimationUtils.currentAnimationTimeMillis() - mStartTime;
            float interpolation = mInterpolator.getInterpolation((float) elapsedTime / mAnimTime);
            interpolation = interpolation > 1 ? 1 : interpolation;
            overScrollDistance -= overScrollDistance * interpolation;
            overScrollDistance = overScrollDistance < 0 ? 0 : overScrollDistance;
        }

        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, overScrollDistance, maxOverScrollY, isTouchEvent);
    }
}

4

1
Android 2.2 是 API 等级 8 - 你是指 2.1 吗? - Izkata
有效的备注:应该是“API级别9”;我已经进行了编辑。 - Marc Van Daele

1
只需使用OverScrollDecoratorHelper
ScrollView scrollView = (ScrollView) findViewById(R.id.scroll_view);
OverScrollDecoratorHelper.setUpOverScroll(scrollView);

HorizontalScrollView horizontalScrollView = (HorizontalScrollView) findViewById(R.id.horizontal_scroll_view);
OverScrollDecoratorHelper.setUpOverScroll(horizontalScrollView);

https://github.com/EverythingMe/overscroll-decor


它的功能很棒,除了忽略图层和ScrollView中的元素会覆盖其他所有内容。 - tremon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接