问题
I have a view that's inside a frame layout. I am tracking the ontouch event for the view and I want the view to scroll vertically in a smooth scrolling fashion up and down as I move my finger. At the moment the view scrolls but I can't get the calculation right (and perhaps logic), the scrolling is very choppy. This is similar to Sliding Drawer and for my purpose Sliding Drawer is not going to work.
Would appreciate any help with this problem. Thank you!
cardImage.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
float startY = 0;
float moveY = 0;
float velocityX=0, velocityY=0;
int index = event.getActionIndex();
int action = event.getActionMasked();
int pointerId = event.getPointerId(index);
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
startY = event.getRawY();
isTouchUp = false;
if(mVelocityTracker == null) {
// Retrieve a new VelocityTracker object to watch the velocity of a motion.
mVelocityTracker = VelocityTracker.obtain();
}
else {
// Reset the velocity tracker back to its initial state.
mVelocityTracker.clear();
}
// Add a user's movement to the tracker.
mVelocityTracker.addMovement(event);
previousRawY = startY;
return true;
case MotionEvent.ACTION_MOVE:
moveY = event.getRawY();
isTouchUp = false;
mVelocityTracker.addMovement(event);
// When you want to determine the velocity, call
// computeCurrentVelocity(). Then call getXVelocity()
// and getYVelocity() to retrieve the velocity for each pointer ID.
mVelocityTracker.computeCurrentVelocity(1000);
// Log velocity of pixels per second
// Best practice to use VelocityTrackerCompat where possible.
velocityX = VelocityTrackerCompat.getXVelocity(mVelocityTracker, pointerId);
velocityY = VelocityTrackerCompat.getYVelocity(mVelocityTracker, pointerId);
if(Math.abs(velocityX) + 100 > Math.abs(velocityY)) {
// right left
}
else {
// up down
if(action != MotionEvent.ACTION_OUTSIDE) {
if(moveY > previousRawY) {
// Moving down
for(float i=0;i<moveY-previousRawY;i++) {
cardCurrentOffset += (moveY-previousRawY)/(moveY-previousRawY);
cardImage.setTranslationY(cardCurrentOffset);
}
}
else {
// Moving Up
if(cardImage.getY() > topHeaderLayout.getBottom()) {
for(float i=0;i<previousRawY-moveY;i++) {
cardCurrentOffset -= (previousRawY-moveY)/(previousRawY-moveY);
cardImage.setTranslationY(cardCurrentOffset);
}
}
}
previousRawY = moveY;
}
}
return true;
case MotionEvent.ACTION_UP:
isTouchUp = true;
return true;
case MotionEvent.ACTION_CANCEL:
// Return a VelocityTracker object back to be re-used by others.
mVelocityTracker.recycle();
return true;
case MotionEvent.ACTION_OUTSIDE:
return false;
default:
return false;
}
}
});
回答1:
try this one (you can add some checks at the top/bottom or fling as well):
class ScrollingTextView extends TextView {
private GestureDetector mDetector;
public ScrollingTextView(Context context) {
super(context);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 30; i++) {
sb.append("Line #").append(i).append("\n");
}
setTextSize(24);
setText(sb);
setTextColor(0xffeeeeee);
mDetector = new GestureDetector(mListener);
}
private OnGestureListener mListener = new SimpleOnGestureListener() {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
scrollBy(0, (int) distanceY);
return true;
}
};
@Override
public boolean onTouchEvent(MotionEvent event) {
mDetector.onTouchEvent(event);
return true;
}
}
to test it add the following in Activity.onCreate:
View v = new ScrollingTextView(this);
setContentView(v);
回答2:
I've observed that dinamycally changing properties such as margins, isn't as smooth as I'd like. Instead of that I use TranslateAnimations
; the trick is applying animations during the scrolling, and changing the real margins on touch up.
来源:https://stackoverflow.com/questions/19342995/android-smooth-vertical-scroll-on-touch