SCROLLVIEW上下回弹效果的定位BUG

kirophl 2017-09-06 03:52:40
  //要操作的布局
private View innerView;
private float y;
private Rect normal = new Rect();
private Rect normal1 = new Rect();
private boolean animationFinish = true;

public OverScrollView(Context context) {
super(context, null);
}

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

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

private View upLay;

public void setUpLay(View upLay) {

this.upLay = upLay;
}

@Override
protected void onFinishInflate() {
int childCount = getChildCount();
if (childCount > 0) {
innerView = getChildAt(0);

}
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
if (innerView == null) {
return super.onTouchEvent(ev);
} else {
commonTouchEvent(ev);
}
return super.onTouchEvent(ev);
}

private float downY;
private int isUpDetermine = -1;

/**
* 自定义touch事件处理
*
* @param ev
*/
private void commonTouchEvent(MotionEvent ev) {
if (animationFinish) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
y = ev.getY();
downY = y;
break;
case MotionEvent.ACTION_MOVE:
float preY = y == 0 ? ev.getY() : y;
float nowY = ev.getY();
int detailY = (int) (preY - nowY);

y = nowY;
//操作view进行拖动detailY的一半
if (isNeedMove()) {
//布局改变位置之前,记录一下正常状态的位置
if (normal.isEmpty()) {
normal.set(innerView.getLeft(), innerView.getTop(), innerView.getRight(), innerView.getBottom());
}

innerView.layout(innerView.getLeft(), innerView.getTop() - detailY / 4, innerView.getRight(), innerView.getBottom() - detailY / 4);

Log.e("zoubo", "innerView.getTop():" + innerView.getTop()
+ "----innerView.getTop() - detailY:" + (innerView.getTop() - detailY / 4)
+ "---- detailY:" + detailY
+ "----innerView.getBottom() - detailY:" + (innerView.getBottom() - detailY / 4)
+ "innerView.getBottom():" + innerView.getBottom());


}
break;
case MotionEvent.ACTION_UP:
y = 0;
//布局回滚到原来的位置
if (isNeedAnimation()) {
animation();
}
break;
}
}
}


private void animation() {
TranslateAnimation ta = new TranslateAnimation(0, 0, 0, normal.top - innerView.getTop());
ta.setDuration(150);
ta.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
animationFinish = false;
}

@Override
public void onAnimationEnd(Animation animation) {
innerView.clearAnimation();
innerView.layout(normal.left, normal.top, normal.right, normal.bottom);
normal.setEmpty();
animationFinish = true;
}

@Override
public void onAnimationRepeat(Animation animation) {

}
});
innerView.startAnimation(ta);
}

/**
* 判断是否需要回滚
*
* @return
*/
private boolean isNeedAnimation() {
return !normal.isEmpty();
}

/**
* 判断是否需要移动
*
* @return
*/
private boolean isNeedMove() {
int offset = innerView.getMeasuredHeight() - getHeight();
int scrollY = getScrollY();
Log.e("zoubo", "getMeasuredHeight:" + innerView.getMeasuredHeight() + "----getHeight:" + getHeight());
Log.e("zoubo", "offset:" + offset + "----scrollY:" + scrollY);
if (scrollY == 0 || scrollY == offset) {
return true;
}
return false;
}


上下回弹是可以,下拉到回弹区域之后不松手,只要有向下的手势,界面会突然回到最顶部的位置,上拉是向上滑一段,向下滑需要一段距离,突然界面定位到最顶部,求解。。。
观察数据是:
1、头部下拉,getScrollY取得的数字为0
2、底部上拉,getScrollY会成为内容高度减去显示高度,一直不变,但是上滑的话数据会减小,减小到0则出现BUG
求各路大神解答。。。。
...全文
505 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
kirophl 2017-09-08
  • 打赏
  • 举报
回复
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;


/**
 * Created by zhuwenyu on 2017/4/5.
 */

public class OverScrollView extends ScrollView {


    //要操作的布局
    private View innerView;
    private float y;
    private Rect normal = new Rect();
    private Rect normal1 = new Rect();
    private boolean animationFinish = true;

    public OverScrollView(Context context) {
        super(context, null);
    }

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

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


    @Override
    protected void onFinishInflate() {
        int childCount = getChildCount();
        if (childCount > 0) {
            innerView = getChildAt(0);

        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (innerView == null) {
            return super.onTouchEvent(ev);
        } else {
            commonTouchEvent(ev);
        }
        return super.onTouchEvent(ev);
    }

    private float downY;
    private int isUpDetermine = -1;

    /**
     * 自定义touch事件处理
     *
     * @param ev
     */
    private void commonTouchEvent(MotionEvent ev) {
        if (animationFinish) {
            int action = ev.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    y = ev.getY();
                    downY = y;
                    break;
                case MotionEvent.ACTION_MOVE:
                    float preY = y == 0 ? ev.getY() : y;
                    float nowY = ev.getY();
                    int detailY = (int) (preY - nowY);
                    int isUp = 0;  //0为向下滑
                    if (nowY - y <= 0) {
                        isUp = 1;
                    }

                    Log.e("zoubo", "innerView.getTop():" + innerView.getTop()
                            + "----innerView.getTop() - detailY:" + (innerView.getTop() - detailY / 4)
                            + "---- detailY:" + detailY
                            + "----innerView.getBottom() - detailY:" + (innerView.getBottom() - detailY / 4)
                            + "----innerView.getBottom():" + innerView.getBottom() + "------------isup====" + (isUp == 0 ? "下滑" : "上滑"));

//                    if (isUpDetermine != -1) {
//                        if (isUpDetermine != isUp) {
//                            if (innerView.getTop() > 0 || innerView.getBottom() < getHeight()) {
//                                if (isUp == 0) {
//                                    Log.e("come", "1");
//                                    animation();
//                                } else {
//                                    Log.e("come", "2");
//                                    animation();
//                                }
//                            }
//                        }
//                    }
//                    isUpDetermine = isUp;

                    y = nowY;
                    //操作view进行拖动detailY的一半
                    if (isNeedMove()) {
                        //布局改变位置之前,记录一下正常状态的位置
                        if (normal.isEmpty()) {
                            normal.set(innerView.getLeft(), innerView.getTop(), innerView.getRight(), innerView.getBottom());
                        }

                        innerView.layout(innerView.getLeft(), innerView.getTop() - detailY / 4, innerView.getRight(), innerView.getBottom() - detailY / 4);

                        normal1.set(innerView.getLeft(), innerView.getTop(), innerView.getRight(), innerView.getBottom());

                    }
                    break;
                case MotionEvent.ACTION_UP:
                    y = 0;
                    //布局回滚到原来的位置
                    if (isNeedAnimation()) {
                        animation();
                    }
                    break;
            }
        }
    }


    private void animation() {
        TranslateAnimation ta = new TranslateAnimation(0, 0, 0, normal.top - innerView.getTop());
        ta.setDuration(150);
        ta.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                animationFinish = false;
            }

            @Override
            public void onAnimationEnd(Animation animation) {

                innerView.clearAnimation();
                innerView.layout(normal.left, normal.top, normal.right, normal.bottom);
                normal.setEmpty();
                animationFinish = true;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        innerView.startAnimation(ta);
    }

    /**
     * 判断是否需要回滚
     *
     * @return
     */
    private boolean isNeedAnimation() {
        return !normal.isEmpty();
    }

    /**
     * 判断是否需要移动
     *
     * @return
     */
    private boolean isNeedMove() {
        int offset = innerView.getMeasuredHeight() - getHeight();
        int scrollY = getScrollY();
        Log.e("zoubo", "getMeasuredHeight:" + innerView.getMeasuredHeight() + "----getHeight:" + getHeight());
        Log.e("zoubo", "offset:" + offset + "----scrollY:" + scrollY);
        if (scrollY == 0 || scrollY == offset) {
            return true;
        }
        return false;
    }

}
楼上的代码红字太多,这楼的应该可以直接带进去。
kirophl 2017-09-08
  • 打赏
  • 举报
回复
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;


/**
 * Created by zhuwenyu on 2017/4/5.
 */

public class OverScrollView extends ScrollView {


    //要操作的布局
    private View innerView;
    private float y;
    private Rect normal = new Rect();
    private Rect normal1 = new Rect();
    private boolean animationFinish = true;

    public OverScrollView(Context context) {
        super(context, null);
    }

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

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

    private View upLay;

    public void setUpLay(View upLay) {

        this.upLay = upLay;
    }

    @Override
    protected void onFinishInflate() {
        int childCount = getChildCount();
        if (childCount > 0) {
            innerView = getChildAt(0);

        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (innerView == null) {
            return super.onTouchEvent(ev);
        } else {
            commonTouchEvent(ev);
        }
        return super.onTouchEvent(ev);
    }

    private float downY;
    private int isUpDetermine = -1;

    /**
     * 自定义touch事件处理
     *
     * @param ev
     */
    private void commonTouchEvent(MotionEvent ev) {
        if (animationFinish) {
            int action = ev.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    y = ev.getY();
                    downY = y;
                    break;
                case MotionEvent.ACTION_MOVE:
                    float preY = y == 0 ? ev.getY() : y;
                    float nowY = ev.getY();
                    int detailY = (int) (preY - nowY);
                    int isUp = 0;  //0为向下滑
                    if (nowY - y <= 0) {
                        isUp = 1;
                    }

                    Log.e("zoubo", "innerView.getTop():" + innerView.getTop()
                            + "----innerView.getTop() - detailY:" + (innerView.getTop() - detailY / 4)
                            + "---- detailY:" + detailY
                            + "----innerView.getBottom() - detailY:" + (innerView.getBottom() - detailY / 4)
                            + "----innerView.getBottom():" + innerView.getBottom() + "------------isup====" + (isUp == 0 ? "下滑" : "上滑"));

//                    if (isUpDetermine != -1) {
//                        if (isUpDetermine != isUp) {
//                            if (innerView.getTop() > 0 || innerView.getBottom() < getHeight()) {
//                                if (isUp == 0) {
//                                    Log.e("come", "1");
//                                    animation();
//                                } else {
//                                    Log.e("come", "2");
//                                    animation();
//                                }
//                            }
//                        }
//                    }
//                    isUpDetermine = isUp;

                    y = nowY;
                    //操作view进行拖动detailY的一半
                    if (isNeedMove()) {
                        //布局改变位置之前,记录一下正常状态的位置
                        if (normal.isEmpty()) {
                            normal.set(innerView.getLeft(), innerView.getTop(), innerView.getRight(), innerView.getBottom());
                        }

                        innerView.layout(innerView.getLeft(), innerView.getTop() - detailY / 4, innerView.getRight(), innerView.getBottom() - detailY / 4);

                        if (getScrollY() == 0) {
                            Log.e("zoubo", "innerView.getTop():" + innerView.getTop()
                                    + "----innerView.getTop() - detailY:" + (innerView.getTop() - detailY / 4)
                                    + "---- detailY:" + detailY
                                    + "----innerView.getBottom() - detailY:" + (innerView.getBottom() - detailY / 4)
                                    + "innerView.getBottom():" + innerView.getBottom());
                        }

                        if (innerView.getTop() == 0 && normal1.left != 0) {
                            innerView.layout(normal1.left, normal1.top - detailY / 4, normal1.right, normal1.bottom - detailY / 4);
                        }

                        normal1.set(innerView.getLeft(), innerView.getTop(), innerView.getRight(), innerView.getBottom());

                        //上方不变,上拉下方不是背景图片
                        if (innerView.getMeasuredHeight() - innerView.getBottom() > 0) {
                            this.setBackgroundColor(0xfff6f6f6);
                            upLay.setBackgroundResource(R.drawable.red_grad);
                        } else {
                            this.setBackgroundResource(R.drawable.red_grad);
                            upLay.setBackgroundColor(0x00000000);
                        }

                    }
                    break;
                case MotionEvent.ACTION_UP:
                    y = 0;
                    //布局回滚到原来的位置
                    if (isNeedAnimation()) {
                        animation();
                    }
                    break;
            }
        }
    }


    private void animation() {
        TranslateAnimation ta = new TranslateAnimation(0, 0, 0, normal.top - innerView.getTop());
        ta.setDuration(150);
        ta.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                animationFinish = false;
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                OverScrollView.this.setBackgroundResource(R.drawable.red_grad);
                upLay.setBackgroundColor(0x00000000);
                normal1.setEmpty();

                innerView.clearAnimation();
                innerView.layout(normal.left, normal.top, normal.right, normal.bottom);
                normal.setEmpty();
                animationFinish = true;
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        innerView.startAnimation(ta);
    }

    /**
     * 判断是否需要回滚
     *
     * @return
     */
    private boolean isNeedAnimation() {
        return !normal.isEmpty();
    }

    /**
     * 判断是否需要移动
     *
     * @return
     */
    private boolean isNeedMove() {
        int offset = innerView.getMeasuredHeight() - getHeight();
        int scrollY = getScrollY();
        Log.e("zoubo", "getMeasuredHeight:" + innerView.getMeasuredHeight() + "----getHeight:" + getHeight());
        Log.e("zoubo", "offset:" + offset + "----scrollY:" + scrollY);
        if (scrollY == 0 || scrollY == offset) {
            return true;
        }
        return false;
    }

}
完整代码如上
kirophl 2017-09-08
  • 打赏
  • 举报
回复
引用 2 楼 xj396282771 的回复:
试了一下你的代码,你这个完全没你说的效果啊,也没得你说的BUG
抱歉没说全,需要继承SCROLLVIEW
kirophl 2017-09-08
  • 打赏
  • 举报
回复
我自己试了一下,确实简单界面没问题,,,我再自己查查 谢谢大哥了!
Jing丶無雙 2017-09-08
  • 打赏
  • 举报
回复
依旧没效果啊 主界面:
package com.example.solveproblem;

import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		LinearLayout scroll = (LinearLayout) findViewById(R.id.scroll);
	}

}
XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <com.example.solveproblem.OverScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:id="@+id/scroll"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <TextView
                android:layout_width="match_parent"
                android:layout_height="700dp"
                android:background="#708090" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="700dp"
                android:background="#7FFFD4" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="700dp"
                android:background="#66CD00" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="700dp"
                android:background="#8B5A2B" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="700dp"
                android:background="#CD919E" />
        </LinearLayout>
    </com.example.solveproblem.OverScrollView>
</LinearLayout>
Jing丶無雙 2017-09-07
  • 打赏
  • 举报
回复
试了一下你的代码,你这个完全没你说的效果啊,也没得你说的BUG
kirophl 2017-09-07
  • 打赏
  • 举报
回复
自己顶一波自己顶一波自己顶一波

80,360

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧