ViewPager setCurrentItem (pageId, true) НЕ плавает
Я компилирую на SDK 4.03, Samsung Infuse Android 2.2, библиотеку поддержки для Android 4 и используя ViewPager в своем приложении, фактический салфетки отлично работает, но когда я делаю
viewPager.setCurrentItem(id); // , or
viewPager.setCurrentItem(id, true);
Он не сглаживает прокрутку, но мгновенно переключает представления. Хотя в документации четко указано, что это цель, устанавливающая второй аргумент true. Что с этим?
Ответы
Ответ 1
Я исправил это, создав MyViewPager, который переопределяет ViewPager.mScroller, используя отражение.
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*/);
}
}
}
Ответ 2
Это то, что я сделал. Я переопределил метод private-private 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);
}
}
Он отлично поработал, если вы хотите, чтобы вы могли рассчитать и обеспечить фактическую скорость ISO всего за 1.
Ответ 3
Я вызвал функцию setCurrentItem
в обработчике, и он отлично работал у меня.
new Handler().post(new Runnable() {
@Override
public void run() {
myViewPager.setCurrentItem(1, true);
}
});
Надеюсь, что это поможет.
Ответ 4
Я знаю, что этот поток довольно старый, но это один из лучших результатов Google. Я уже много раз возвращался вперед, чтобы решить эту проблему. Ни одно из решений выше не помогло мне вообще. Однако я нашел решение, которое работает для меня.
В настоящее время моя настройка выглядит как просмотр изнутри viewpager. Когда вы нажимаете на одно из представлений, он создает новую страницу и прокручивает ее. Это было очень быстро, но кажется, что это потому, что я звонил
mViewPager.setCurrentItem(intIndex, true);
изнутри моего OnClickEvent. По какой-то причине viewpager не нравится, поэтому вместо этого я сделал эту функцию. Он создает новый поток, который запускает 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 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, и он должен работать. Возьмите это с солью, хотя я еще не проверял ее.
Ответ 5
ViewPager сильно изменился с 5 по 9. Некоторые из этих изменений могут быть связаны с вашей проблемой:
- Исправлены ошибки для поведения пользовательского интерфейса в ViewPager (версии 5 и 6).
- Исправлено множество ошибок для ViewPager (версия 9)
Давая понять, что ваш код должен работать нормально, я полагаю, что ваша библиотека поддержки не обновляется. Попробуйте обновить библиотеку, если это не так.
Ответ 6
Я создал этот класс, потому что я не был полностью удовлетворен вышеуказанными решениями
Класс переопределяет setCurrentItem(int item, boolean smoothScroll)
и использует отражение, чтобы сохранить этот метод как можно более оригинальным. Ключевым моментом является то, что скорость не равна 0. Вам нужно только заменить текущий ViewPager
на этот класс MyViewPager
и использовать его как обычно:
import android.content.Context;
import android.util.AttributeSet;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import androidx.viewpager.widget.ViewPager;
public class MyViewPager extends ViewPager {
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Set the currently selected page. If the ViewPager has already been through its first
* layout with its current adapter there will be a smooth animated transition between
* the current item and the specified item.
*
* @param item Item index to select
* @param smoothScroll True to smoothly scroll to the new item, false to transition immediately
*/
@Override
public void setCurrentItem(int item, boolean smoothScroll) {
final Class<?> viewpager = ViewPager.class;
int velocity = 1;
try {
Field mPopulatePending = viewpager.getDeclaredField("mPopulatePending");
mPopulatePending.setAccessible(true);
mPopulatePending.set(this, false);
Method setCurrentItemInternal = viewpager.getDeclaredMethod("setCurrentItemInternal", int.class, boolean.class, boolean.class, int.class);
setCurrentItemInternal.setAccessible(true);
setCurrentItemInternal.invoke(this, item, smoothScroll, false, velocity);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Ответ 7
У меня была та же проблема, но сегодня я нашел простое решение. Может быть, это поможет вам.
Во-первых, давайте предположим, что у нас есть ViewPager, который заполняет весь экран. Чтобы переключаться между страницами, я создал собственный пользовательский вид с вкладками и поместил его поверх ViewPager. Щелчок на вкладке должен плавно прокручиваться на соответствующую страницу в ViewPager с помощью setCurrentItem (item, true) - но он прокручивается мгновенно, без каких-либо плавности! Затем я попытался добавить простую кнопку (не пользовательскую) через обратный вызов ViewPager +:
@Override
public void onClick(View v) {
viewPager.setCurrentItem(item, true);
}
После этого гладкий свиток смотрел на работу. Итак, решение было очень простым: внутри класса Button внутренний булевский onTouch (...) прослушиватель возвращает true, поэтому он всегда ПОТРЕБИТ события касания! Затем гладкая прокрутка начала работать для моего пользовательского представления вкладок, когда я заменил "return false" на "return true" во внутреннем булевом onTouch (...) прослушивателе.
Я надеюсь, что моя история успеха поможет вам.
Ответ 8
Для тех, кто использует Xamarin (хотя этот подход применим и к Java), я могу предложить использовать следующий подход на основе вышеприведенного ответа (ViewPager из Android Support Library v7 AppCompat 19.1.0):
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 из http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/support/v4/view/ViewPager.java
Ответ 9
Потратив весь свой день, я нашел решение с установленным offscreenPageLimit на общее количество нет. страницы.
пожалуйста, следуйте этому fooobar.com/questions/102600/...
Ответ 10
Обратите внимание на эту переменную mFirstLayout
- она будет установлена в значение true при обратном onAttachedToWindow
viewpager для onAttachedToWindow
(например, в обзоре реселлера) onAttachedToWindow
поэтому не будет 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();
}
}
Ответ 11
попробуйте этот код:
viewPager.postDelayed(new Runnable()
{
@Override
public void run()
{
viewPager.setCurrentItem(id, true);
}
}, 100);