Как сделать круговую прокрутку на ViewPager?
Я хочу, чтобы мой ViewPager выполнял круговую прокрутку. Я хочу, чтобы первая страница могла прокручиваться до страницы 2 И последней страницы. И мне бы хотелось, чтобы моя последняя страница прокручивалась до [последней страницы -1] и первой страницы. Я сделал попытку, хотя я не уверен, когда нужно вызвать метод, который я создал. В ViewPager, похоже, не существует метода, который обрабатывает такие вещи, поэтому я создал ниже.
public ViewPagerAdapter(final ViewPager pager, int... pageIDs) {
super();
int actualNoOfIDs = pageIDs.length;
count = actualNoOfIDs + 2;
Log.d(TAG, "actualNoOfIDs: " + actualNoOfIDs +
"count: " + count);
pageIDsArray = new int[count];
for (int i = 0; i < actualNoOfIDs; i++) {
pageIDsArray[ i + 1] = pageIDs[i];
}
pageIDsArray[0] = pageIDs[actualNoOfIDs - 1];
pageIDsArray[count - 1] = pageIDs[0];
Log.d(TAG, "actualNoOfIDs#2: " + actualNoOfIDs +
"count#2: " + count);
pager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
int pageCount = getCount();
if (position == 0) {
pager.setCurrentItem(pageCount - 2, false);
} else if (position == pageCount - 1) {
pager.setCurrentItem(1, false);
}
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
Log.d(TAG, "onPageScrollStateChanged()");
// if (state == ViewPager.SCROLL_STATE_IDLE) {
// int pageCount = getCount();
// int currentItem = pager.getCurrentItem();
// if (currentItem == 0) {
// pager.setCurrentItem(pageCount - 2, false);
// } else if (currentItem == pageCount - 1) {
// pager.setCurrentItem(1, false);
// }
// }
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
// TODO Auto-generated method stub
Log.d(TAG, "onPageScrolled()");
}
});
}
Весь мой код довольно длинный, но если это помогает, я могу его опубликовать.
public class ViewPagerAdapter extends PagerAdapter {
public static String TAG = ViewPagerAdapter.class.getSimpleName();
private int count;
private int[] pageIDsArray;
private TextToSpeech btnTTS;
private TtsButton tTSBtn;
String inputTxt;
Context context;
View itemView;
TextView tvNumber; // container for atomic number
TextView tvSymbol; // container for symbol
TextView tvWeight; // container for weight
TextView tvName; // container for name
TextView tvGroup; // container for group
TextView tvPeriod; // container for period
TextView tvBlock; // container for block
TextView tvFamily; // container for family
TextView tvColor; // container for color
TextView tvPhase; // container for phase
TextView tvMelt; // container for melting point
TextView tvBoil; // container for boiling point
TextView tvNeutrons; // container for neutrons
TextView tvProtons; // container for protons
TextView tvElectrons; // container for electrons
TextView tvUrl; // container for electrons
public ViewPagerAdapter(Context context, List<Integer> arrayAtomicNum,
List<String> arrayName, List<String> arraySymbol, List<String> arrayFamily,
List<String> arrayPhase, List<String> arrayColor, List<Integer> arrayGroup,
List<Integer> arrayPeriod, List<String> arrayBlock, List<Integer> arrayProtons,
List<Integer> arrayNeutrons, List<Integer> arrayElectrons, List<Double> arrayWeight,
List<Double> arrayMelt, List<Double> arrayBoil, List<String> arrayUrl) {
this.context = context;
ElementStructure.arrayAtomicNum = arrayAtomicNum;
ElementStructure.arrayName = arrayName;
ElementStructure.arraySymbol = arraySymbol;
ElementStructure.arrayFamily = arrayFamily;
ElementStructure.arrayPhase = arrayPhase;
ElementStructure.arrayColor = arrayColor;
ElementStructure.arrayGroup = arrayGroup;
ElementStructure.arrayPeriod = arrayPeriod;
ElementStructure.arrayBlock = arrayBlock;
ElementStructure.arrayProtons = arrayProtons;
ElementStructure.arrayNeutrons = arrayNeutrons;
ElementStructure.arrayElectrons = arrayElectrons;
ElementStructure.arrayWeight = arrayWeight;
ElementStructure.arrayMelt = arrayMelt;
ElementStructure.arrayBoil = arrayBoil;
ElementStructure.arrayUrl = arrayUrl;
}
public ViewPagerAdapter(final ViewPager pager, int... pageIDs) {
super();
int actualNoOfIDs = pageIDs.length;
count = actualNoOfIDs + 2;
Log.d(TAG, "actualNoOfIDs: " + actualNoOfIDs +
"count: " + count);
pageIDsArray = new int[count];
for (int i = 0; i < actualNoOfIDs; i++) {
pageIDsArray[ i + 1] = pageIDs[i];
}
pageIDsArray[0] = pageIDs[actualNoOfIDs - 1];
pageIDsArray[count - 1] = pageIDs[0];
Log.d(TAG, "actualNoOfIDs#2: " + actualNoOfIDs +
"count#2: " + count);
pager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
int pageCount = getCount();
if (position == 0) {
pager.setCurrentItem(pageCount - 2, false);
} else if (position == pageCount - 1) {
pager.setCurrentItem(1, false);
}
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
Log.d(TAG, "onPageScrollStateChanged()");
// if (state == ViewPager.SCROLL_STATE_IDLE) {
// int pageCount = getCount();
// int currentItem = pager.getCurrentItem();
// if (currentItem == 0) {
// pager.setCurrentItem(pageCount - 2, false);
// } else if (currentItem == pageCount - 1) {
// pager.setCurrentItem(1, false);
// }
// }
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
// TODO Auto-generated method stub
Log.d(TAG, "onPageScrolled()");
}
});
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return ElementStructure.arrayAtomicNum.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
// TODO Auto-generated method stub
return view == ((RelativeLayout) object);
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int layoutColorId = ElementStructure.arrayLayoutColor.get(position);
if (layoutColorId == 1) {
itemView = inflater.inflate(R.layout.frame_learn_a, container,
false);
} else if (layoutColorId == 2) {
itemView = inflater.inflate(R.layout.frame_learn_b, container,
false);
} else if (layoutColorId == 3) {
itemView = inflater.inflate(R.layout.frame_learn_c, container,
false);
} else if (layoutColorId == 4) {
itemView = inflater.inflate(R.layout.frame_learn_d, container,
false);
}
Button btnSpeak = (Button)itemView.findViewById(R.id.btnaudio);
btnSpeak.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
inputTxt = ElementStructure.arrayName.get(position);
tTSBtn = new TtsButton(this, inputTxt);
}
});
// atomic number textView
tvNumber = (TextView)itemView.findViewById(R.id.metanumber);
// symbol textView
tvSymbol = (TextView)itemView.findViewById(R.id.metasymbol);
// weight textView
tvWeight = (TextView)itemView.findViewById(R.id.metaweight);
// name textView
tvName = (TextView)itemView.findViewById(R.id.metaname);
// group textView
tvGroup = (TextView)itemView.findViewById(R.id.metagroup);
// period textView
tvPeriod = (TextView)itemView.findViewById(R.id.metaperiod);
// block textView
tvBlock = (TextView)itemView.findViewById(R.id.metablock);
// family textView
tvFamily = (TextView)itemView.findViewById(R.id.metafamily);
// color textView
tvColor = (TextView)itemView.findViewById(R.id.metacolor);
// phase textView
tvPhase = (TextView)itemView.findViewById(R.id.metaphase);
// melting point textView
tvMelt = (TextView)itemView.findViewById(R.id.metamelt);
// boiling point textView
tvBoil = (TextView)itemView.findViewById(R.id.metaboil);
// neutrons textView
tvNeutrons = (TextView)itemView.findViewById(R.id.metaneutrons);
// protons textView
tvProtons = (TextView)itemView.findViewById(R.id.metaprotons);
// electrons textView
tvElectrons = (TextView)itemView.findViewById(R.id.metaelectrons);
// url textView
tvUrl = (TextView)itemView.findViewById(R.id.metaurl);
// capture position and set to the TextViews
tvNumber.setText(String.valueOf(ElementStructure.arrayAtomicNum.get(position)));
tvSymbol.setText(ElementStructure.arraySymbol.get(position));
tvWeight.setText(String.valueOf(ElementStructure.arrayWeight.get(position)));
tvName.setText(ElementStructure.arrayName.get(position));
tvPeriod.setText(String.valueOf(ElementStructure.arrayPeriod.get(position)));
tvBlock.setText(String.valueOf(ElementStructure.arrayBlock.get(position)));
tvFamily.setText(ElementStructure.arrayFamily.get(position));
tvColor.setText(ElementStructure.arrayColor.get(position));
tvPhase.setText(ElementStructure.arrayPhase.get(position));
tvNeutrons.setText(String.valueOf(ElementStructure.arrayNeutrons.get(position)));
tvProtons.setText(String.valueOf(ElementStructure.arrayProtons.get(position)));
tvElectrons.setText(String.valueOf(ElementStructure.arrayElectrons.get(position)));
tvUrl.setText(ElementStructure.arrayUrl.get(position));
// capture position, adjust for 0 value cases
if (ElementStructure.arrayGroup.get(position) == 0) {
tvGroup.setText("n/a");
} else {
tvGroup.setText(String.valueOf(ElementStructure.arrayGroup.get(position)));
}
if (ElementStructure.arrayMelt.get(position) == 0) {
tvMelt.setText("n/a");
} else {
tvMelt.setText(String.valueOf(ElementStructure.arrayMelt.get(position)));
}
if (ElementStructure.arrayBoil.get(position) == 0) {
tvBoil.setText("n/a");
} else {
tvBoil.setText(String.valueOf(ElementStructure.arrayBoil.get(position)));
}
// add fragments to container (ViewPager)
((ViewPager) container).addView(itemView);
return itemView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Log.d(TAG, "destroyItem()");
// remove fragments from container (ViewPager)
((ViewPager) container).removeView((RelativeLayout) object);
}
@Override
public void finishUpdate(View container) {
// TODO Auto-generated method stub
Log.d(TAG, "finishUpdate()");
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
// TODO Auto-generated method stub
Log.d(TAG, "restoreState()");
}
@Override
public Parcelable saveState() {
// TODO Auto-generated method stub
Log.d(TAG, "saveState()");
return null;
}
@Override
public void startUpdate(View container) {
// TODO Auto-generated method stub
Log.d(TAG, "startUpdate()");
}
public class TtsButton extends Activity implements OnInitListener {
public TtsButton(OnClickListener onClickListener, String inputTxt) {
super();
tTSCheck(inputTxt);
}
private void tTSCheck (String inputTxt) {
int resultCodeCheck = TextToSpeech.Engine.CHECK_VOICE_DATA_PASS;
if (resultCodeCheck == 1) {
btnTTS = new TextToSpeech(context, this);
} else {
Intent installTTSFiles = new Intent(); //missing data, install it
installTTSFiles.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installTTSFiles);
}
}
@Override
public void onInit(int status) {
// TODO Auto-generated method stub
if(status == TextToSpeech.SUCCESS)
{
Log.i(TAG, "TTS INIT: SUCCESS");
btnTTS.setLanguage(Locale.US);
btnTTS.speak(inputTxt, TextToSpeech.QUEUE_FLUSH, null);
}
else if(status == TextToSpeech.ERROR)
{
Log.e(TAG, "TTS INIT: ERROR");
}
}
@Override
public void onPause() {
if (btnTTS != null) {
btnTTS.stop();
btnTTS.shutdown();
}
super.onPause();
}
} //end embedded class
} //end ViewPagerAdapter
Спасибо заранее. Я думал о попытке использовать жест движения, однако, я действительно не понимаю, почему мой метод не будет работать так долго, что я могу назвать его в правильном месте. Моя первоначальная мысль заключалась в том, чтобы вызвать его в "Object instantiateItem (контейнер ViewGroup, конечная позиция int)" каждый раз, когда позиция изменяется, и если условия были правильными. Но я не уверен, что это лучше всего.
Ответы
Ответ 1
Хорошо, у меня есть ответ. Это было на самом деле легче, чем я ожидал, но это требует некоторого обмана. Во-первых, позвольте мне начать с создания. Допустим, например, у вас есть три страницы (A-B-C), которые вы прокручиваете в своем ViewPager. И вы хотите настроить его так, чтобы, если вы продолжаете прокручивать C (стр. 3), он переходит к A (стр. 1), и если вы прокручиваете назад на A (стр. 1), он переходит на C (стр. 3)).
Я не говорю, что мое решение - лучшее, но оно работает, и я не вижу никаких проблем. Во-первых, вам нужно создать две "поддельные" страницы. Поддельные страницы представляют собой первую и последнюю страницы вашего ViewPager. Следующее, что вам понадобится, это настроить onPageChangeListener() и использовать метод onPageSelected(). Причина, по которой вам нужны поддельные страницы, - это то, что onPageSelected() регистрируется только после перемещения (swiped). Другими словами, без этого метода конечный пользователь должен будет прокручиваться до страницы 2 и вернуться на страницу 1, чтобы получить попадание на страницу 1, что также означает, что страница 1 будет пропущена в зависимости от вашей логики кода.
Настройка - это действительно весь ответ. Когда у вас есть свои поддельные страницы, это просто вопрос использования setCurrentItem() внутри необходимого метода.
Вот как выглядит мой код. Обязательно поместите это в свой общедоступный Object instantiateItem (окончательный контейнер ViewGroup, конечная позиция int) непосредственно перед возвратом вашего представления внутри вашего контейнера.
((ViewPager) container).setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
Log.d(TAG, "onPageSelected() :: " + "position: " + position);
// skip fake page (first), go to last page
if (position == 0) {
((ViewPager) container).setCurrentItem(118, false);
}
// skip fake page (last), go to first page
if (position == 119) {
((ViewPager) container).setCurrentItem(1, false); //notice how this jumps to position 1, and not position 0. Position 0 is the fake page!
}
}
Что это, он делает трюк! Единственное, что нужно сделать, это запустить свой ViewPager в позиции 1 (это вторая страница: fake page = pg 1, моя реальная стартовая страница = pg 2). Теперь, каждый раз, когда я просматриваю поддельную страницу, я перенаправляю ее назад на последнюю реальную страницу. И каждый раз, когда я прокручиваю страницу до последней поддельной страницы, я перенаправляю ее вперед на настоящую стартовую страницу (стр. 2).
Кроме того, не пытайтесь помещать какой-либо код в onPageScrollStateChanged. Этот метод причудливый, кажется, что значение состояния неуправляемо. Он постоянно перескакивает из одного состояния в другое. Даже без прокрутки. Это всего лишь подсказка, которую я взял.
Ответ 2
Это решение без поддельных страниц и работает как шарм:
public class CircularViewPagerHandler implements ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
private int mCurrentPosition;
private int mScrollState;
public CircularViewPagerHandler(final ViewPager viewPager) {
mViewPager = viewPager;
}
@Override
public void onPageSelected(final int position) {
mCurrentPosition = position;
}
@Override
public void onPageScrollStateChanged(final int state) {
handleScrollState(state);
mScrollState = state;
}
private void handleScrollState(final int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
setNextItemIfNeeded();
}
}
private void setNextItemIfNeeded() {
if (!isScrollStateSettling()) {
handleSetNextItem();
}
}
private boolean isScrollStateSettling() {
return mScrollState == ViewPager.SCROLL_STATE_SETTLING;
}
private void handleSetNextItem() {
final int lastPosition = mViewPager.getAdapter().getCount() - 1;
if(mCurrentPosition == 0) {
mViewPager.setCurrentItem(lastPosition, false);
} else if(mCurrentPosition == lastPosition) {
mViewPager.setCurrentItem(0, false);
}
}
@Override
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
}
}
Вам просто нужно установить его в свой ViewPager как onPageChangeListener и что он:
viewPager.setOnPageChangeListener(new CircularViewPagerHandler(viewPager));
Чтобы избежать синего блеска на "конце" вашего ViewPager, вы должны применить эту строку к своему xml, где размещен ViewPager:
android:overScrollMode="never"
Ответ 3
Я создал круговой viewpager с плавным прокруткой от последнего до первого в салфетке слева и сначала до последнего во время салфетки справа.
для этого добавьте последнюю страницу в начале и первой странице до последней:
внутри addOnPageChangeListener: мы должны сделать некоторые вычисления, когда мы находимся в 0 позиции, а затем onPageScrollStateChanged задает текущий элемент как последний элемент и наоборот.
Посмотрите на код
public class ViewPagerCircular_new extends AppCompatActivity {
ViewPager viewPager;
ArrayList<String> str = new ArrayList<String>();
boolean chageImage = false;
int setPos;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.view_pager_normal);
viewPager = (ViewPager) findViewById(R.id.vf_home_top_pager);
str.add("6"); // added the last page to the frist
str.add("1"); // First item to display in view pager
str.add("2");
str.add("3");
str.add("4");
str.add("5");
str.add("6"); // last item to display in view pager
str.add("1"); // added the first page to the last
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
if (position == str.size() - 1)
{
chageImage = true;
setPos = 1;
} else if (position == 0)
{
chageImage = true;
setPos = str.size() - 2;
} else
{
chageImage = false;
}
}
@Override
public void onPageSelected(int position)
{
}
@Override
public void onPageScrollStateChanged(int state)
{
if (state == ViewPager.SCROLL_STATE_IDLE && chageImage)
{
viewPager.setCurrentItem(setPos, false);
}
}
});
// display the 1st item as current item
viewPager.setCurrentItem(1);
}
//адаптер пейджера
public class ViewPagerAdapter extends FragmentStatePagerAdapter
{
public ViewPagerAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public Fragment getItem(int position)
{
PagerFragment fragment = new PagerFragment();
Bundle bundle = new Bundle();
bundle.putString("pos", str.get(position));
fragment.setArguments(bundle);
return fragment;
}
@Override
public int getCount()
{
return str.size();
}
}
//фрагмент для отображения в адаптере
public class PagerFragment extends Fragment
{
Bundle bundle;
String pos;
public PagerFragment()
{
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
bundle = getArguments();
pos = bundle.getString("pos");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
TextView textView = new TextView(ViewPagerCircular_new.this);
textView.setGravity(Gravity.CENTER);
textView.setTextSize(25);
textView.setText(pos);
return textView;
}
}
}
Ответ 4
Попробуйте это
((ViewPager) container)
.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
Log.i("TAG", "pos::" + position);
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
int currentPage = pager.getCurrentItem();
Log.i("TAG", "currentPage::" + currentPage);
Log.i("TAG", "currentState::" + currentState);
Log.i("TAG", "previousState::" + previousState);
if (currentPage == 4 || currentPage == 0) {
previousState = currentState;
currentState = state;
if (previousState == 1 && currentState == 0) {
pager.setCurrentItem(currentPage == 0 ? 4 : 0);
}
}
}
@Override
public void onPageScrolled(int arg0, float arg1,
int arg2) {
// TODO Auto-generated method stub
}
});
return
Это должно быть помещено внутри
@Override
public Object instantiateItem(final View container, int position) {}
Ответ 5
Я немного изменил ответ от @portfoliobuilder. Это очень просто.
Установка текущего элемента без плавной прокрутки до PageChangeState
для "0", поэтому он будет очень плавным.
((ViewPager)container).setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
currentPage = position;
}
@Override
public void onPageScrollStateChanged(int state) {
// state equals to 0 means the scroll action is stop
if(state == 0) {
if(currentPage == 0)
((ViewPager)container).setCurrentItem(imageResourceList.size()-2,false);
if(currentPage == imageResourceList.size()-1)
((ViewPager)container).setCurrentItem(1,false);
}
}
});
Ответ 6
Это мое решение:
myViewPager.java
public class myViewPager extends PagerAdapter {
public myViewPager (Context context) {
this.context = context;
}
@Override
public int getCount() {
return rank.length+2;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// Declare Variables
TextView textViewRank;
//Log.i(TAG, "get position = "+position);
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.viewpager_item, container,
false);
textViewRank= (TextView) itemView.findViewById(R.id.textView1);
if (position == getCount() - 1) {
textViewRank.setText(rank[0]);
} else if (position == 0) {
textViewRank.setText(rank[rank.length-1]);
} else {
textViewRank.setText(rank[position-1]);
}
((ViewPager) container).addView(itemView);
return itemView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
viewpager_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/textView1"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getName();
public static String[] rank;
myViewPager adapter;
private ViewPager viewPager;
private static int currentPage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rank = new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
viewPager = (ViewPager) findViewById(R.id.view_pager);
adapter = new myViewPager(this);
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
Log.i(TAG, "onPageSelected = "+position);
currentPage = position;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// not needed
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
int pageCount = rank.length+2;
if (currentPage == pageCount-1){
viewPager.setCurrentItem(1,false);
} else if (currentPage == 0){
viewPager.setCurrentItem(pageCount-2,false);
}
}
}
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
Предполагается, что массив имеет 10 элементов. Затем добавьте два фиктивных элемента, но не добавьте их. Когда вызывается функция "get_count", просто возвращайте размер = 10 + 2 элемента.
dummy e [0] e [1] e [2] e [3] e [4] e [5] e [6] e [7] e [8] e [9] dummy
В viewPager.addOnPageChangeListener:
когда вы переходите к последнему элементу, viewPager должен установить первый элемент следующим образом.
if (currentPage == pageCount-1){
viewPager.setCurrentItem(1,false);
}
когда вы переходите к первому элементу, viewPager должен установить последний элемент следующим образом.
else if (currentPage == 0){
viewPager.setCurrentItem(pageCount-2,false);
}
В instantiateItem:
if (position == getCount() - 1) {
textViewRank.setText(rank[0]);
} else if (position == 0) {
textViewRank.setText(rank[rank.length-1]);
} else {
textViewRank.setText(rank[position-1]);
}
Ответ 7
Я попробовал решение @portfoliobuilder, это здорово. Но есть крошечная проблема: когда текущий элемент - это голова или хвост, если я просто нажму ViewPager, а не перетащить, элемент изменится на хвост или голову. И я добавил сенсорный прослушиватель ViewPager для решения проблемы.
skinPager.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//Record the x when press down and touch up,
//to judge whether to scroll between head and tail
int x = (int) event.getX();
int y = (int) event.getY();
if(event.getAction() == MotionEvent.ACTION_DOWN)
skinPagerPressX = x;
else if(event.getAction() == MotionEvent.ACTION_UP)
skinPagerUpX = x;
return false;
}
});
Ниже приведена измененная функция portfoliobuilder:
private void handleSetNextItem() {
final int lastPosition = skinPager.getAdapter().getCount() - 1;
//Only scroll when dragged
if(mCurrentPosition == 0 && skinPagerUpX > skinPagerPressX) {
skinPager.setCurrentItem(lastPosition, false);
} else if(mCurrentPosition == lastPosition && skinPagerUpX < skinPagerPressX) {
skinPager.setCurrentItem(0, false);
}
}
Ответ 8
Ответ @tobi_b не является полностью успешным, так как он не плавно перетекает от последнего к первому (по крайней мере, в моей пробной версии). Но я был действительно вдохновлен его ответом.
Мое решение - когда нужно перепрыгнуть с поддельной последней до реальной, дождитесь окончания последнего прокрутки. Вот мой код, это очень просто,
private final class MyPageChangeListener implements OnPageChangeListener {
private int currentPosition;
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
if (currentPosition == viewPager.getAdapter().getCount() - 1) {
viewPager.setCurrentItem(1, false);
}
else if (currentPosition == 0) {
viewPager.setCurrentItem(viewPager.getAdapter().getCount() - 2, false);
}
}
}
@Override
public void onPageScrolled(int scrolledPosition, float percent, int pixels) {
//empty
}
@Override
public void onPageSelected(int position) {
currentPosition = position;
}
}
Однако это решение не является совершенным. У этого есть небольшой недостаток, когда слайд быстро от последнего к первому. Если мы сдвинем два раза за очень короткое время, второй слайд станет недействительным. Эта проблема должна быть решена.
Ответ 9
Исправлено отсутствие анимации при движении справа налево при прокрутке первой страницы до последней и наоборот
Небольшая модификация ответа @tobi_b, решила мою проблему.
для этого добавьте копию последней страницы в начале и первой странице до последней. Затем просто удалите оператор NOT из приведенного ниже метода в PagerAdapter. И измените setCurrentItem (lastposition, false) на setCurrentItem (lastposition-1, false) и setCurrentItem (0, false) в setCurrentItem (1, false).
private void setNextItemIfNeeded() {
if (isScrollStateSettling()) {
handleSetNextItem();
}
}
private boolean isScrollStateSettling() {
return mScrollState == ViewPager.SCROLL_STATE_SETTLING;
}
private void handleSetNextItem() {
final int lastPosition = pager.getAdapter().getCount() - 1;
if(mCurrentPosition == 0) {
pager.setCurrentItem(lastPosition-1, false);
} else if(mCurrentPosition == lastPosition) {
pager.setCurrentItem(1, false);
}
}
И в вашем MainActivity.java не забудьте установить текущий элемент как 1.
Надеюсь, это поможет некоторым.
Ответ 10
Это простой пример, важной частью слушателя является обнаружение STATE_IDLE конечной точки цикла. поэтому сначала реализуйте класс OnPageChangeListener, затем в своем классе обработчика добавьте эту часть:
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
if (mPreviousPosition == mCurrentPosition && !mIsEndOfCycle) {
if (mCurrentPosition == 0) {
mViewPager.setCurrentItem(getAdapterItemsCount() - 1);
} else {
mViewPager.setCurrentItem(0);
}
mIsEndOfCycle = true;
} else {
mIsEndOfCycle = false;
}
mPreviousPosition = mCurrentPosition;
}
}