我正在编译SDK 4.03,三星Infuse Android 2.2,Android 4支持库,并在我的应用程序中使用ViewPager,实际滑动工作正常,但当我做
viewPager.setCurrentItem(id); // , or
viewPager.setCurrentItem(id, true);
它不会平滑滚动,但会立即切换视图。虽然文档明确指出这是将第二个参数设置为true的目的。怎么了?
答案 0 :(得分:42)
我通过创建一个使用反射覆盖ViewPager.mScroller的MyViewPager来解决这个问题。
public class MyViewPager extends ViewPager {
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setMyScroller();
}
private void setMyScroller() {
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
scroller.set(this, new MyScroller(getContext()));
} catch (Exception e) {
e.printStackTrace();
}
}
public class MyScroller extends Scroller {
public MyScroller(Context context) {
super(context, new DecelerateInterpolator());
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, 1000 /*1 secs*/);
}
}
}
答案 1 :(得分:16)
这就是我所做的。我通过将自己的自定义子类放在同一个包中来覆盖smoothScrollTo
中的包私有方法ViewPager
。它传递的值为零,这会导致捕捉行为而不是平滑滚动。
package android.support.v4.view;
import android.content.Context;
import android.util.AttributeSet;
public class MyViewPager extends ViewPager {
public MyViewPager(Context context) {
super(context);
}
public MyViewPager(Context context, AttributeSet attr) {
super(context, attr);
}
void smoothScrollTo(int x, int y, int velocity) {
super.smoothScrollTo(x, y, 1);
}
}
它很有效,如果你想要你可以计算并提供仅为1的实际速度ISO。
答案 2 :(得分:9)
我在处理程序中调用了setCurrentItem
函数,它对我来说很好。
new Handler().post(new Runnable() {
@Override
public void run() {
myViewPager.setCurrentItem(1, true);
}
});
希望这有帮助。
答案 3 :(得分:6)
我知道这个帖子很老了,但这是Google最重要的结果之一。我一直在回顾如何解决这个问题。上面的解决方案都没有帮助我。但是,我确实找到了适合我的解决方案。
我目前的设置是viewpager中的listview。当您单击其中一个视图时,它会创建一个新页面并滚动到该页面。这之前非常活泼,但似乎这是因为我打电话
mViewPager.setCurrentItem(intIndex, true);
来自我的OnClickEvent。由于某种原因,viewpager不喜欢这个,所以相反,我做了这个功能。它创建了一个在UI线程上运行runnable的新线程。这个runnable告诉ViewPager滚动到某个项目。
public static void scrollToIndex(int index) {
final int intIndex = index;
//We're going to make another thread to separate ourselves from whatever
//thread we are in
Thread sepThread = new Thread(new Runnable(){
public void run()
{
//Then, inside that thread, run a runnable on the ui thread.
//MyActivity.getContext() is a static function that returns the
//context of the activity. It's useful in a pinch.
((Activity)MyActivity.getContext()).runOnUiThread(new Runnable(){
@Override
public void run() {
if (mSlidingTabLayout != null)
{
//I'm using a tabstrip with this as well, make sure
//the tabstrip is updated, or else it won't scroll
//correctly
if(mSlidingTabLayout.getTabStripChildCount() <= intIndex)
mSlidingTabLayout.updateTabStrip();
//Inside this thread is where you call setCurrentItem
mViewPager.setCurrentItem(intIndex, true);
}
}
});
}
});
sepThread.start();
}
我希望我至少能帮助解决这个问题的人。祝你好运!
编辑:看看我的回答,我很确定你可以在ui线程上运行,它应该可以工作。拿着那粒盐,但我还没有测试过。
答案 4 :(得分:1)
ViewPager已经从版本5改为很多。其中一些可能与您的问题有关的更改:
假设你的代码应该运行得很好,我最好的猜测是你的支持库不是最新的。如果不是,请尝试更新库。
答案 5 :(得分:1)
我之所以创建这个类是因为我对上述解决方案不完全满意
该类重写import pandas as pd
# Empty list to store dataframe rows
df_rows = []
# Read all text files
for tf in text_files:
# For each file
with open(tf) as f:
# Empty dictionary to store column names and values
df_dict = {}
# For each line
for line in f:
# Split by tab
k, v = line.split('\t')
# Column name as key, value as value
df_dict[k] = v
# Add the dictionary to list
df_rows.append(df_dict)
# Read the list of dictionaries as a dataframe
df = pd.DataFrame(df_rows)
# Preview dataframe
df.head()
并使用反射使该方法尽可能保持原始。关键是速度不为0。
您只需用此setCurrentItem(int item, boolean smoothScroll)
类替换当前的ViewPager
并像往常一样使用它即可:
MyViewPager
答案 6 :(得分:0)
我遇到了同样的问题,但今天我找到了一个简单的解决方案。也许它会帮助你。 首先,假设我们有一个填充整个屏幕的ViewPager。要在页面之间切换,我已经使用制表符创建了我自己的自定义视图并将其放在ViewPager上。单击选项卡应使用setCurrentItem(item,true)顺利滚动到ViewPager中的相应页面 - 但它会立即滚动,没有平滑!然后我尝试在ViewPager +回调上添加一个简单的按钮(不是自定义):
@Override
public void onClick(View v) {
viewPager.setCurrentItem(item, true);
}
之后,顺畅的滚动盯着工作。因此,解决方案非常简单:在Button类内部,内部布尔值onTouch(...)侦听器返回true,因此它总是消耗触摸事件!然后,当我在内部布尔值onTouch(...)侦听器中用“return true”替换“return false”时,平滑滚动开始为我的自定义选项卡视图工作。
我希望我的成功故事可以帮助你。
答案 7 :(得分:0)
对于那些使用Xamarin的人(虽然这种方法也适用于Java)我可以根据上面的答案建议使用下一种方法(来自Android支持库v7 AppCompat 19.1.0的ViewPager):
public void ScrollSmooth(int i)
{
var jClass = JNIEnv.GetObjectClass(_pager.Handle);
var jMethod = JNIEnv.GetMethodID(jClass, "setCurrentItemInternal", "(IZZI)V");
JNIEnv.CallVoidMethod (_pager.Handle, jMethod, new JValue (i), new JValue (true), new JValue (false), new JValue (1));
}
中的ViewPager实现
答案 8 :(得分:0)
浪费了一整天后,我发现一个解决方案将offscreenPageLimit设置为总数。页面的
。答案 9 :(得分:0)
请注意此变量mFirstLayout
-
在viewpager回调onAttachedToWindow
时(例如在recyclerview上)将其设置为true,因此不会使用smoothScroll。您应该重写onAttachedToWindow以控制mFirstLayout
变量。像这样:
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
try {
Field mFirstLayout = ViewPager.class.getDeclaredField("mFirstLayout");
mFirstLayout.setAccessible(true);
mFirstLayout.set(this, false);
getAdapter().notifyDataSetChanged();
setCurrentItem(getCurrentItem());
} catch (Exception e) {
e.printStackTrace();
}
}
答案 10 :(得分:0)
下面的代码将暂停页面一会儿(500毫秒),然后滑动到下一个页面。
import androidx.viewpager.widget.ViewPager;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
viewPager.setCurrentItem(index, true);
}
}, 500);
答案 11 :(得分:0)
正如其他人后来发现的那样,这是一个错误,我们不得不延迟发布,但这可能非常简单:
pager.post {
pager.setCurrentItem(1, true)
}
可悲的是,您必须尝试第一堆错误答案才能解决此问题……
答案 12 :(得分:-5)
尝试使用此代码:
viewPager.postDelayed(new Runnable()
{
@Override
public void run()
{
viewPager.setCurrentItem(id, true);
}
}, 100);