gpt4 book ai didi

Android:基于速度的 ViewPager 滚动

转载 作者:IT王子 更新时间:2023-10-28 23:54:58 26 4
gpt4 key购买 nike

ViewPager 现在滚动的方式是每个手势一个项目。无论是全屏快闪还是慢拖,对挥动手势的处理方式都是一样的;在最后一页只前进了一步。

是否有任何项目或示例可能会添加基于速度的 throw ,根据现有 throw 的速度滚动多个项目(如果仍在进行中)并在 throw 手势又宽又快时进一步滚动?

如果没有从哪里开始这样的事情?

附:提供赏金。请不要引用 Gallery 或 Horizo​​ntalScrollView 的答案

最佳答案

这里的技术是扩展 ViewPager 并模仿寻呼机将在内部执行的大部分操作,以及来自 Gallery 小部件的滚动逻辑。总体思路是监控弹跳(以及速度和伴随的滚动),然后将它们作为虚假的拖动事件提供给底层的 ViewPager。如果您单独执行此操作,则将无法正常工作(您仍然只能获得一页滚动)。发生这种情况是因为假拖动在滚动有效的边界上实现了上限。您可以在扩展的 ViewPager 中模拟计算并检测何时会发生这种情况,然后只需翻页并照常继续。使用假拖动的好处意味着您不必处理捕捉到页面或处理 ViewPager 的边缘。

我在动画演示示例中测试了以下代码,可从 http://developer.android.com/training/animation/screen-slide.html 下载通过用这个 VelocityViewPager 替换 ScreenSlideActivity 中的 ViewPager(在布局 activity_screen_slide 和 Activity 中的字段中)。

/*
* Copyright 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Dororo @ StackOverflow
* An extended ViewPager which implements multiple page flinging.
*
*/

package com.example.android.animationsdemo;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.GestureDetector;
import android.widget.Scroller;

public class VelocityViewPager extends ViewPager implements GestureDetector.OnGestureListener {

private GestureDetector mGestureDetector;
private FlingRunnable mFlingRunnable = new FlingRunnable();
private boolean mScrolling = false;

public VelocityViewPager(Context context) {
super(context);
}

public VelocityViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(context, this);
}

// We have to intercept this touch event else fakeDrag functions won't work as it will
// be in a real drag when we want to initialise the fake drag.
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
// give all the events to the gesture detector. I'm returning true here so the viewpager doesn't
// get any events at all, I'm sure you could adjust this to make that not true.
mGestureDetector.onTouchEvent(event);
return true;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) {
mFlingRunnable.startUsingVelocity((int)velX);
return false;
}

private void trackMotion(float distX) {

// The following mimics the underlying calculations in ViewPager
float scrollX = getScrollX() - distX;
final int width = getWidth();
final int widthWithMargin = width + this.getPageMargin();
final float leftBound = Math.max(0, (this.getCurrentItem() - 1) * widthWithMargin);
final float rightBound = Math.min(this.getCurrentItem() + 1, this.getAdapter().getCount() - 1) * widthWithMargin;

if (scrollX < leftBound) {
scrollX = leftBound;
// Now we know that we've hit the bound, flip the page
if (this.getCurrentItem() > 0) {
this.setCurrentItem(this.getCurrentItem() - 1, false);
}
}
else if (scrollX > rightBound) {
scrollX = rightBound;
// Now we know that we've hit the bound, flip the page
if (this.getCurrentItem() < (this.getAdapter().getCount() - 1) ) {
this.setCurrentItem(this.getCurrentItem() + 1, false);
}
}

// Do the fake dragging
if (mScrolling) {
this.fakeDragBy(distX);
}
else {
this.beginFakeDrag();
this.fakeDragBy(distX);
mScrolling = true;
}

}

private void endFlingMotion() {
mScrolling = false;
this.endFakeDrag();
}

// The fling runnable which moves the view pager and tracks decay
private class FlingRunnable implements Runnable {
private Scroller mScroller; // use this to store the points which will be used to create the scroll
private int mLastFlingX;

private FlingRunnable() {
mScroller = new Scroller(getContext());
}

public void startUsingVelocity(int initialVel) {
if (initialVel == 0) {
// there is no velocity to fling!
return;
}

removeCallbacks(this); // stop pending flings

int initialX = initialVel < 0 ? Integer.MAX_VALUE : 0;
mLastFlingX = initialX;
// setup the scroller to calulate the new x positions based on the initial velocity. Impose no cap on the min/max x values.
mScroller.fling(initialX, 0, initialVel, 0, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);

post(this);
}

private void endFling() {
mScroller.forceFinished(true);
endFlingMotion();
}

@Override
public void run() {

final Scroller scroller = mScroller;
boolean animationNotFinished = scroller.computeScrollOffset();
final int x = scroller.getCurrX();
int delta = x - mLastFlingX;

trackMotion(delta);

if (animationNotFinished) {
mLastFlingX = x;
post(this);
}
else {
endFling();
}

}
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distX, float distY) {
trackMotion(-distX);
return false;
}

// Unused Gesture Detector functions below

@Override
public boolean onDown(MotionEvent event) {
return false;
}

@Override
public void onLongPress(MotionEvent event) {
// we don't want to do anything on a long press, though you should probably feed this to the page being long-pressed.
}

@Override
public void onShowPress(MotionEvent event) {
// we don't want to show any visual feedback
}

@Override
public boolean onSingleTapUp(MotionEvent event) {
// we don't want to snap to the next page on a tap so ignore this
return false;
}

}

这有一些小问题,可以很容易地解决,但我会留给你,比如如果你滚动(拖动,而不是扔)你可能会在页面之间结束(你会想要捕捉 ACTION_UP 事件)。此外,为了做到这一点,触摸事件被完全覆盖,因此您需要在适当的情况下将相关事件提供给底层 ViewPager

关于Android:基于速度的 ViewPager 滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12787287/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com