アプリで新聞のページを表示するための水平スワイプにPagerAdapterを使用しています。
現在、このアプリに循環スクロールを実装したいと思っています。今私が行ったことはwhenever I am getting on last page I try to set the currentItem to first page
、つまり最後のページから最初のページまで機能する機能ですが、問題は最初から最後のページに移動する方法です。ページ。ここでは、pagerAdapterとonPageChangeListenerに関連するコードを貼り付けています:-
awesomeAdapter = new AwesomePagerAdapter(awesomePager);
awesomePager.setAdapter(awesomeAdapter);
awesomePager.setPageMargin(10);
awesomePager.setOnPageChangeListener(new OnPageChangeListener() {
int lastPosition;
float posOffset = 0;
@Override
public void onPageSelected(int position) {
viewerPage = position;
CommonLogic.logMessage("Viewer Page:- "+ viewerPage, TAG, Log.VERBOSE);
posOffset = 0;
}
@Override
public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels) {
if (positionOffset == 0 && positionOffsetPixels == 0 && position != 0) {
lastPosition = position;
}
posOffset -= positionOffset;
CommonLogic.logMessage(" Position:- "
+ position + " Position Offset:- " + positionOffset
+ " Position Offset Variable:- "
+ posOffset
+ " Position Offset Pixels:- "
+ positionOffsetPixels
+ " Last Position " + lastPosition,
TAG, Log.VERBOSE);
CommonLogic.logMessage(" Last Position "
+ lastPosition, TAG, Log.VERBOSE);
}
@Override
public void onPageScrollStateChanged(int state) {
// To Detect the Last Page & This Sets it to first page.This working fine.
if (state == ViewPager.SCROLL_STATE_DRAGGING && viewerPage == (uris.size() - 1)) {
CommonLogic.logMessage("Scroll State Changed ", TAG,Log.VERBOSE);
postDelayed(new Runnable() {
@Override
public void run() {
awesomePager.setCurrentItem(0, true);
}
}, 200);
}
// I have also used this to detect whether the user is on first & try to move on last page,but it is not working well.
else if (state == ViewPager.SCROLL_STATE_DRAGGING && (lastPosition == 0 || lastPosition == (uris.size() - 1)) && viewerPage == 0 && posOffset <= 0) {
CommonLogic.logMessage( "Scroll State Changed ", TAG,Log.VERBOSE);
postDelayed(new Runnable() {
@Override
public void run() {
awesomePager.setCurrentItem((uris.size() - 1), true);
}
}, 200);
}
}
}
});
また、PagerAdapter、つまり私の場合はAwesomweAdapterも、次のようになります。-
private class AwesomePagerAdapter extends PagerAdapter {
ViewPager pdfContainer;
DocumentNewView documentNewView;
CustomViewPager customViewPager;
public AwesomePagerAdapter(CustomViewPager awesomePager) {
this.customViewPager = awesomePager;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public int getCount() {
return uris.size();
}
public DocumentNewView addViewAt(int position, DocumentNewView mainView) {
CommonLogic.logMessage("Position of View:- " + position, TAG,
Log.VERBOSE);
pdfContainer.addView(mainView);
return mainView;
}
/**
* Create the page for the given position. The adapter is responsible
* for adding the view to the container given here, although it only
* must ensure this is done by the time it returns from
* {@link #finishUpdate()}.
*
* @param container
* The containing View in which the page will be shown.
* @param position
* The page position to be instantiated.
* @return Returns an Object representing the new page. This does not
* need to be a View, but can be some other container of the
* page.
*/
@Override
public Object instantiateItem(View collection, int position) {
CommonLogic
.logMessage("Instantiate Item Called ", TAG, Log.VERBOSE);
documentNewView = new DocumentNewView(cxt, display, customViewPager);
documentNewView.setPdfContext(new PdfContext());
CodecDocument codecDocument = documentNewView.open(uris
.get(position));
documentNewView.renderDocument(codecDocument);
documentNewView.setMaxZoom(4f);
documentNewView.setVerticalScrollBarEnabled(true);
codecDocument = null;
this.pdfContainer = (ViewPager) collection;
return addViewAt(position, documentNewView);
}
/**
* Remove a page for the given position. The adapter is responsible for
* removing the view from its container, although it only must ensure
* this is done by the time it returns from {@link #finishUpdate()}.
*
* @param container
* The containing View from which the page will be removed.
* @param position
* The page position to be removed.
* @param object
* The same object that was returned by
* {@link #instantiateItem(View, int)}.
*/
@Override
public void destroyItem(View collection, int position, Object view) {
pdfContainer.removeView((DocumentNewView) view);
}
/**
* Called when the a change in the shown pages has been completed. At
* this point you must ensure that all of the pages have actually been
* added or removed from the container as appropriate.
*
* @param container
* The containing View which is displaying this adapter's
* page views.
*/
@Override
public void finishUpdate(View arg0) {
CommonLogic.logMessage("Finish Update Called ", TAG, Log.VERBOSE);
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void startUpdate(View arg0) {
CommonLogic.logMessage("State Update Called ", TAG, Log.VERBOSE);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == ((DocumentNewView) object);
}
私のコード(該当する場合)の提案/変更を教えてください。前もって感謝します。
これは、onPageSelected
のOnPageChangeListener
メソッドをオーバーライドすることで実現できます。この順序で3つのページがあると考えてください_A<->B<->C
_。目標は、C
から右にスクロールするとA
に到達することであり、同様にA
から左にスクロールするとC
に到達することです。
これを行うには、5ページ(3 + 2)になるように定義し、次のようにページを整理します。
C
_<->A<->B<->C<->
_A
ここで、onPageSelected
メソッドで、位置が_0
_かどうかを確認し、_3
_(getCount()-2
)に変更し、位置が_4
_(getCount()-1
)、_1
_に変更します。必ず次の方法を使用してください。
_setCurrentItem(item, smoothScroll)
_
CircularPagerAdaptorクラスの完全なコードは次のとおりです。
_package zolender.adapters;
import Android.content.Context;
import Android.os.Parcelable;
import Android.support.v4.view.PagerAdapter;
import Android.support.v4.view.ViewPager;
import Android.support.v4.view.ViewPager.OnPageChangeListener;
import Android.view.LayoutInflater;
import Android.view.View;
public class CircularPagerAdapter extends PagerAdapter{
private int[] pageIDsArray;
private int count;
public CircularPagerAdapter(final ViewPager pager, int... pageIDs) {
super();
int actualNoOfIDs = pageIDs.length;
count = actualNoOfIDs + 2;
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];
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 onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
}
});
}
public int getCount() {
return count;
}
public Object instantiateItem(View container, int position) {
LayoutInflater inflater = (LayoutInflater) container.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int pageId = pageIDsArray[position];
View view = inflater.inflate(pageId, null);
((ViewPager) container).addView(view, 0);
return view;
}
@Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public void finishUpdate(View container) {
// TODO Auto-generated method stub
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == ((View) object);
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
// TODO Auto-generated method stub
}
@Override
public Parcelable saveState() {
// TODO Auto-generated method stub
return null;
}
@Override
public void startUpdate(View container) {
// TODO Auto-generated method stub
}
}
_
そして、これがあなたがそれを使うことができる方法です:
_myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
PagerAdapter adapter = new CircularPagerAdapter(myPager, new int[]{R.layout.farleft, R.layout.left, R.layout.middle, R.layout.right, R.layout.farright});
myPager.setAdapter(adapter);
myPager.setCurrentItem(3);
_
円形のViewPagerも必要でした。これは私がやったことです。どこかからpageCount値を取得していると思います。
...
pager = (ViewPager) findViewById(R.id.pager);
//Gesture detection
final GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector());
pager.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
//pagelistener is just for getting selected page
pager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
selectedPage = position;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
これがGestureDetectorです。 ここ からコピー
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int SWIPE_MIN_DISTANCE = Utils.ConvertToPixel(mContext, 50);
int SWIPE_MAX_OFF_PATH = Utils.ConvertToPixel(mContext, 250);
int SWIPE_THRESHOLD_VELOCITY = Utils.ConvertToPixel(mContext, 200);
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
&& selectedPage == (pageCount - 1)) {
pager.setCurrentItem(0);
return true;
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
&& selectedPage == 0) {
pager.setCurrentItem(pageCount - 1);
return true;
}
} catch (Exception e) {
// nothing
}
return false;
}
}
Z0lenDer の答えを拡張すると、関連付けられたビューごとにメモリを解放する必要がない通常のViewPager
を使用する場合、作成されたビューを保存するよりも効率的です。レイアウトID。これは、アイテムの切り替え時に遅延やちらつきを取り除きたい場合に必要です。
onPageSelected
を使用すると、切り替えを行う前にスライドが終了しないため、アニメーションにも問題があります。これを回避する唯一の方法は、スクロール状態がSCROLL_STATE_IDLE
に変更された後でのみ切り替えを実行し、現在のアイテムをonPageSelected
に設定することです。
private int currentPage = 0;
.。
pager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
currentPage = position;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
Log.d(TAG, "onPageScrollStateChanged: " + state);
if (state == ViewPager.SCROLL_STATE_IDLE) {
int pageCount = getCount();
if (currentPage == 0){
pager.setCurrentItem(pageCount-2,false);
} else if (currentPage == pageCount-1){
pager.setCurrentItem(1,false);
}
}
}
});
これを試して
((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) {}
まあこれは助けた
private class CircularViewPagerHandler implements ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
private int mCurrentPosition;
private int mScrollState;
private int mPreviousPosition;
public CircularViewPagerHandler(final ViewPager viewPager) {
mViewPager = viewPager;
}
@Override
public void onPageSelected(final int position) {
mCurrentPosition = position;
mPreviousPosition = position-1;
}
@Override
public void onPageScrollStateChanged(final int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
setNextItemIfNeeded();
}
mScrollState = state;
}
private void setNextItemIfNeeded() {
if (!isScrollStateSettling()) {
handleSetNextItem();
}
}
private boolean isScrollStateSettling() {
return mScrollState == ViewPager.SCROLL_STATE_SETTLING; //indicated page is settling to it's final position
}
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) {
}
}
@tobi_bの answer でした
私はそれをこのように使用しました、アダプター0> 1> 2> 3> 4> 5、0&5のフラグメントレイアウトはダミーです
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(1, false); //going to page 1;
final int[] pagePosition = new int[1];
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
pagePosition[0] = position;
}
@Override
public void onPageScrollStateChanged(int state) { //state changes from 2 to 0 during a swipe
if (state == 0 && pagePosition[0] == 0){
viewPager.setCurrentItem(4, false);
} else if (state == 0 && pagePosition[0] == 5){
viewPager.setCurrentItem(1, false);
}
}
});