I've twenty images in my app.. I make use of ViewPager to show the previous/next images when the user swipes left/right in the app?? I would like to show "Repeat" screen when the user swipes to the right in the last image..
Here is my code,
viewPager = (ViewPager) findViewById(R.id.main_viewpager);
ImagePagerAdapter adapter = new ImagePagerAdapter();
viewPager.setAdapter(adapter);
PageListener pageListener = new PageListener();
viewPager.setOnPageChangeListener((OnPageChangeListener) pageListener);
int currentPage;
private class PageListener extends SimpleOnPageChangeListener{
public void onPageSelected(int position) {
--- some code -----
currentPage = position;
}
}
private class ImagePagerAdapter extends PagerAdapter {
#Override
public int getCount() {
return mImages.size();
}
-- other implemented methods ---
}
Is it possible to capture the event when the user swipes to the right of the last element in the viewpager??
You can achieve this by setting a custom onChangePageListener on your ViewPager like you started. I'd do it like:
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
//...
#Override
public void onPageSelected(int arg0) {
onPageChanged(arg0);
}
//...
});
And then in your activity
public void onPageChanged(int position) {
if(position == SOMETHING) //do something
}
Hope this helps
what you can do is grab an instance of the viewpager and call :
PagerAdapter pg = viewPager.getAdapter();
int i = pg.getCount();
this will return the count of pages in viewPager now what you can do is:
apply a condition to check your current page with the total count...
note that first page is [0] 2nd is [1] and 3rd is [2]...the current page's count is returned by...
viewPager.getCurrentItem()
Hope this solves your problem!
From this link:
You can extend ViewPager class and then override onTouchEvent() method:
Here for an example:
public class MxTViewPager extends ViewPager {
public MxTViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
float mStartDragX;
OnSwipeOutListener mListener;
public void setOnSwipeOutListener(OnSwipeOutListener listener) {
mListener = listener;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (getCurrentItem() == getAdapter().getCount() - 1) {
final int action = ev.getAction();
float x = ev.getX();
switch (action & MotionEventCompat.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mStartDragX = x;
break;
case MotionEvent.ACTION_UP:
if (x < mStartDragX) {
mListener.onSwipeOutAtEnd();
} else {
mStartDragX = 0;
}
break;
}
} else {
mStartDragX = 0;
}
return super.onTouchEvent(ev);
}
public interface OnSwipeOutListener {
public void onSwipeOutAtEnd();
}
}
Hope it can help you!
Related
I have made an app in which I have added functionality of vertical swipe using ViewPager class. Now I need help to show Admob Interstitial ad after 5 swipes. I have seen several other SO question but could not get clarity.
Can anyone help me how can I do this? Here is my code:
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mains);
mData = dbHelper.getAll(Data.class);
DATA_CARDS = mData.size();
ScreenSlidePagerAdapter screenSlidePagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
VerticalViewPager verticalViewPager = (VerticalViewPager) findViewById(R.id.pager);
verticalViewPager.setAdapter(screenSlidePagerAdapter);
}
ScreenSlidePagerAdapter
public class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
private static final int NUM_PAGES = MainActivity.DATA_CARDS;
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
SlidingFragment slidingFragment = new SlidingFragment();
Bundle bundle = new Bundle();
bundle.putInt("position", position);
slidingFragment.setArguments(bundle);
return slidingFragment;
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
VerticalViewPager
public class VerticalViewPager extends ViewPager {
public VerticalViewPager(Context context) {
super(context);
init();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setPageTransformer(true, new VerticalPageTransformer());]
setOverScrollMode(OVER_SCROLL_NEVER);
}
private class VerticalPageTransformer implements ViewPager.PageTransformer {
#Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
view.setAlpha(1);
// Counteract the default slide transition
view.setTranslationX(view.getWidth() * -position);
//set Y position to swipe in from top
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
/**
* Swaps the X and Y coordinates of your touch event.
*/
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev); // return touch coordinates to original reference frame for any child views
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
}
You can add the PageChangeListener to your view pager and call the onPageSelected() calls, for this you need to have class field called e.g. int mAdCounter = 0:
verticalViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
mAdCount++;
if (mAdCount % 5 == 0) {
//Display your add
//It's better if you load the ad before you need to display it, you can hide the adview and load it
} else {
//Hide the adView
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
I've tried to implement swiperefreshlayout in my code but it keeps refreshing the entire pager instead of just refreshing when i'm on the first Fragment i.e the 0th Fragment.
I tried setting refresh to false as shown, but the loader still appears, and doesn't reset when I go back to the 0th Fragment again.
On setting swiperefreshlayout.enable(false), I can't refresh it anywhere.
Can anyone suggest an alternative?
This is my XML file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parentLinearLayout"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<lbbdapp.littleblackbook.com.littleblackbook.Support.VerticalViewPager
android:id="#+id/verticalViewPager"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
And this is my activity:
public class FeedActivity extends ActionBarActivity {
PageAdapter mPageAdapter;
ProgressBar mProgressBar;
ProgressDialog prog;
ViewPager pager;
String article_id;
private float x1, x2;
SwipeRefreshLayout mSwipeRefreshLayout;
ArrayList<FragmentObject> mObjectsDataList;
ArrayList<ArticleObject> mArticleDataList=new ArrayList<ArticleObject>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.feed_layout);
mObjectsDataList = new ArrayList<FragmentObject>();
DataFetcherTask myTask = new DataFetcherTask();
myTask.execute();
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
mSwipeRefreshLayout.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_blue_dark,
android.R.color.holo_purple,
android.R.color.darker_gray);
pager=(ViewPager)findViewById(R.id.verticalViewPager);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
if(pager.getCurrentItem()==0) {
Log.wtf("current item is 0", "0");
mSwipeRefreshLayout.setRefreshing(true);
Log.wtf("Swiping", "Refreshing");
(new Handler()).postDelayed(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
DataFetcherTask myTask = new DataFetcherTask();
myTask.execute();
}
}, 3000);
}
else{
mSwipeRefreshLayout.setRefreshing(false);
}
}
});
}
This is my vertical ViewPager:
public class VerticalViewPager extends ViewPager {
public VerticalViewPager(Context context) {
super(context);
init();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// The majority of the magic happens here
setPageTransformer(true, new VerticalPageTransformer());
// The easiest way to get rid of the overscroll drawing that happens on the left and right
setOverScrollMode(OVER_SCROLL_NEVER);
}
private class VerticalPageTransformer implements ViewPager.PageTransformer {
#Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
view.setAlpha(1);
// Counteract the default slide transition
view.setTranslationX(view.getWidth() * -position);
//set Y position to swipe in from top
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
/**
* Swaps the X and Y coordinates of your touch event.
*/
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev); // return touch coordinates to original reference frame for any child views
return intercepted;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
}
Instead of extending SwipeRefesh over ViewGroup use it inside the each Fragment of ViewPager.
Once this is resolved now you need to check scroll down gesture of ViewPager and SwipeRefresh.
public class NEWSwipeRefresh extends SwipeRefreshLayout {
private View mTargetView;
public NEWSwipeRefresh(Context context) {
this(context, null);
}
public NEWSwipeRefresh(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setTarget(View view) {
mTargetView = view;
}
#Override
public boolean canChildScrollUp() {
if (mTargetView instanceof YOURVIEW) {
final StaggeredGridView absListView = (YOURVIEW)mTargetView;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView
.getChildAt(0).getTop() < absListView
.getPaddingTop());
} else {
return super.canChildScrollUp();
}
}
}
Normally swipe refresh returns -1 and it gives swipe gesture to it's parent now I have overridden it here for listview/gridview so that it can check for visible items, if it is on top then it will give swipe to parent or otherwise it will give it to children.
Well, I was trying to figure this out since few days and it's quite simple. Just put the SwipeRefreshLayout as the parent element of ViewPager and just disable the SwipeRefreshLayout on the particular fragment using OnPageChangeListener as follows:
// viewpager change listener
OnPageChangeListener viewPagerPageChangeListener = new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
//for the 0th pos disable SwipeRefreshLayout;
if(position != 0){
swipeRefreshLayout.setEnabled(false);
}else swipeRefreshLayout.setEnabled(true);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}};
I am using ViewPager with FragmentStatePageAdapter to show a number of views where user can go through. With current implementation only one page is changed at any single swipe. Instead I want to flip through multiple views based on user swipe. If swipe is long/fast i need to flip through multiple views and vice versa.
here is my current code
public class MyAdapter extends FragmentStatePagerAdapter
{
public MyAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public int getCount() {
return 10;
}
#Override
public Fragment getItem(int position) {
return ItemFragment.init(position);
}
}
PageContainer class
public class PagerContainer extends FrameLayout implements ViewPager.OnPageChangeListener {
private ViewPager mPager;
boolean mNeedsRedraw = false;
public PagerContainer(Context context) {
super(context);
init();
}
public PagerContainer(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PagerContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
//Disable clipping of children so non-selected pages are visible
setClipChildren(false);
//Child clipping doesn't work with hardware acceleration in Android 3.x/4.x
//You need to set this value here if using hardware acceleration in an
// application targeted at these releases.
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
#Override
protected void onFinishInflate() {
try {
mPager = (ViewPager) getChildAt(0);
mPager.setOnPageChangeListener(this);
} catch (Exception e) {
throw new IllegalStateException("The root child of PagerContainer must be a ViewPager");
}
}
public ViewPager getViewPager() {
return mPager;
}
private Point mCenter = new Point();
private Point mInitialTouch = new Point();
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCenter.x = w / 2;
mCenter.y = h / 2;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
//We capture any touches not already handled by the ViewPager
// to implement scrolling from a touch outside the pager bounds.
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mInitialTouch.x = (int)ev.getX();
mInitialTouch.y = (int)ev.getY();
default:
ev.offsetLocation(mCenter.x - mInitialTouch.x, mCenter.y - mInitialTouch.y);
break;
}
return mPager.dispatchTouchEvent(ev);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Force the container to redraw on scrolling.
//Without this the outer pages render initially and then stay static
if (mNeedsRedraw) invalidate();
}
#Override
public void onPageSelected(int position) { }
#Override
public void onPageScrollStateChanged(int state) {
mNeedsRedraw = (state != ViewPager.SCROLL_STATE_IDLE);
}
}
How can I do this in android?
Thanks
You can change the view by calling:
ViewPager.setCurrentItem(int index)
ViewPager.setCurrentItem(int index, bool animation)
You must handle the sliding commands yourself, but on a certain slide you cloud call setCurrentItem of the ViewPager. The setCurrentItem method also allows you to enable or disable animations.
I'm using viewpager and populating it with 4 fragments.
I cannot upload images to show what it looks like. However, I have uploaded the images to a picture hosting website and have included the link to the image here.
What I need is: http://postimg.org/image/3l4h53ucl/
However, what I can currently get to work is: http://postimg.org/image/m5kauitzr/
How can I fix this?
I have seen this being done perfectly on a viewpager with 3 pages:ViewPager - get a partial view of the next page
MainActivity.java Global Variables
PagerAdapter myPagerAdapter;
ViewPager myPager;
List<Fragment> myDefaultFragments;
MainActivity.java
myDefaultFragments = new Vector<Fragment>();
myDefaultFragments.add(Fragment.instantiate(this, SettingsFragment.class.getName()));
myDefaultFragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
myDefaultFragments.add(Fragment.instantiate(this, FriendsFragment.class.getName()));
myDefaultFragments.add(Fragment.instantiate(this, MessagesFragment.class.getName()));
myPagerAdapter = new PagerAdapter(this.getSupportFragmentManager(), myDefaultFragments);
myPager = (ViewPager) findViewById(R.id.viewPager);
myPager.setAdapter(myPagerAdapter);
PagerAdapter.java
public class PagerAdapter extends FragmentPagerAdapter {
private List<Fragment> myFragments;
public PagerAdapter(FragmentManager fm, List<Fragment> fragments){
super(fm);
this.myFragments = fragments;
}
#Override
public Fragment getItem(int whichFrag){
return this.myFragments.get(whichFrag);
}
#Override
public int getCount(){
return this.myFragments.size();
}
#Override
public float getPageWidth(int position) {
if (position == 0 || position == 2){
return 0.9f;
} else if (position == 3) {
return 0.8f;
}
return 1f;
}
}
I don't know exactly what values you need to enter, but you should try some values and check what they do.
My guess:
Position 0: 0.9f
Position 1: 1.3f
Position 2: 1f
Position 3: 0.8f
I'm not sure what the ViewPager does for values larger than 1.0f, but it might work.
change:
#Override
public float getPageWidth(int position) {
if (position == 0 || position == 2){
return 0.9f;
} else if (position == 3) {
return 0.8f;
}
return 1f;
}
to:
#Override
public float getPageWidth(int position) {
switch(position){
case 0:
return 0.9f;
case 1:
return 1.2f;
case 2:
return 1f;
case 3:
return 0.9f;
default:
return 1f;
}
}
I have the following views: a ViewPager that show 3 Fragments. The user can scroll horizontaly to see the others Fragment in the ViewPager.
I need to create an animation, when the Activity is created and the ViewPager is populated, that show the Fragments entering from the right side of the screen.
Is that even possible? Thanks.
XML:
<android.support.v4.view.ViewPager
android:id="#+id/devices"
android:layout_width="wrap_content"
android:layout_height="150dp" />
Activity:
MyFragmentStatePagerAdapter mAdapter = new MyFragmentStatePagerAdapter( this.getSupportFragmentManager(), fragmentArrayList );
mAdapter.setPageWidth(0.33333333f);
ViewPager devices = (ViewPager) view.findViewById(R.id.devices);
devices.setAdapter(sensorAdapter);
Adapter:
public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
ArrayList<Fragment> fragmentsList;
private float pageWidth = 1;
public void setPageWidth(float pageWidth) { this.pageWidth = pageWidth; }
public MyFragmentStatePagerAdapter(FragmentManager fm, ArrayList<Fragment> fragmentsList) {
super(fm);
this.fragmentsList = fragmentsList;
}
#Override
public int getCount() {
return fragmentsList.size();
}
#Override
public Fragment getItem(int position) {
if (position<fragmentsList.size() & fragmentsList.get(position)!=null) {
return fragmentsList.get(position);
}
return null;
}
#Override
public float getPageWidth(int position) {
return(pageWidth);
}
}
OK, I found the solution. I just had to extend ViewPager and do the animation in onDraw.
This code is working as I needed:
public class ViewPagerCustom extends ViewPager {
private Context mContext;
private boolean startAnimationDone = false;
public ViewPagerCustom(Context context) {
super(context);
mContext = context;
init();
}
public ViewPagerCustom(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
DisplayMetrics metrics;
TranslateAnimation anim;
private void init() {
metrics = mContext.getResources().getDisplayMetrics();
anim = new TranslateAnimation(metrics.widthPixels+200, 0, 0, 0);
anim.setInterpolator(new DecelerateInterpolator());
anim.setDuration(500);
}
private Canvas enterAnimation(Canvas c) {
startAnimationDone = true;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
child.startAnimation(anim);
}
return c;
}
#Override
protected void onDraw(Canvas c) {
if (startAnimationDone==false) {
c = enterAnimation(c);
}
super.onDraw(c);
}
}
Here is a link which might help you:
Zoom-out page transformer
It's similar to the accepted solution but uses the same interpolator and only changes the duration based on a factor. You need to use a ViewPagerCustomDuration in your XML instead of ViewPager, and then you can do this:
ViewPagerCustomDuration vp = (ViewPagerCustomDuration) findViewById(R.id.myPager);
vp.setScrollDurationFactor(2); // make the animation twice as slow