Android - ViewPager tab not showing first time - android

I have a tablayout with viewpager and a recyclerview inside... I've override the onMeasure method... The first time I open the fragment, the fragment inside the viewpager not show, but if i change tab it appear and if i go back to the tab that doesn't show, it begin to show... Can some one help me please!!!
I Think i saw is the viewpager get visible on screen if it fit on the screen, if i need to scroll the screen to see the viewpager it begin hided until i go to another tab and back again to see the content.
I got diferent sizes of contents inside the viewpager, that's why i need to use a custom view pager and override the onMeasure...
The source code below...
THE VIEW PAGER
public class CustomPager extends ViewPager {
private int mCurrentPagePosition = 0;
public CustomPager(Context context) {
super(context);
}
public CustomPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
try {
View child = getChildAt(mCurrentPagePosition);
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
}
} catch (Exception e) {
e.printStackTrace();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void reMeasureCurrentPage(int position) {
mCurrentPagePosition = position;
requestLayout();
}
}
THE SCROLLVIEW
public class CustomScrollView extends ScrollView {
private GestureDetector mGestureDetector;
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(context, new YScrollDetector());
setFadingEdgeLength(0);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev)
&& mGestureDetector.onTouchEvent(ev);
}
// Return false if we're scrolling in the x direction
class YScrollDetector extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return (Math.abs(distanceY) > Math.abs(distanceX));
}
}
}
THE LAYOUT
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="br.com.ole.oleconsignado.ui.fragment.main.LastEntriesFragment">
<View
android:id="#+id/vw_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="#dimen/dimen_mdpi"
android:layout_marginLeft="#dimen/dimen_mdpi"
android:layout_marginRight="#dimen/dimen_mdpi"
android:layout_marginEnd="#dimen/dimen_mdpi"
android:layout_marginStart="#dimen/dimen_mdpi"
android:background="#color/colorGrey"/>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="#color/colorLightBlue"
app:tabSelectedTextColor="#color/colorLightBlue"
android:layout_marginLeft="#dimen/dimen_mdpi"
android:layout_marginRight="#dimen/dimen_mdpi">
<android.support.design.widget.TabItem
android:id="#+id/tab_national"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/title_national" />
<android.support.design.widget.TabItem
android:id="#+id/tab_international"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/title_international" />
</android.support.design.widget.TabLayout>
<br.com.ole.oleconsignado.util.CustomScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<br.com.ole.oleconsignado.util.CustomPager
android:id="#+id/vp_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/dimen_mdpi" />
</br.com.ole.oleconsignado.util.CustomScrollView>
</LinearLayout>
I realy don't know why it happen... Please, help me!
Here some examples similar...
Set Viewpager height inside Scrollview in android
getchildat() method returns null for last position (3rd Fragment in my case) Fragment for WarpContent ViewPager Android
ViewPager wrap_content not working
Android - ViewPager tab not showing first time

Sorry I couldn't understan your use-case completely but I think I can help.
Are You Trying to get any sort Dimensional-Measurements from the activity?
If Yes Then unfortunately the activities and fragments are not completely generated until onPause()
but you can try to do this-
Create a variable of your parent layout in your activity ;
RelativeLayout canvas;
canvas = (RelativeLayout) findViewById(R.id.canvas);
canvas.getViewTreeObserver().addOnGlobalLayoutListener(new
ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
canvas.getViewTreeObserver().removeOnGlobalLayoutListener(this);
/* Code to get dimensional measurements */
}
});
Hope It Helps :)

Related

RecyclerView inside viewpager

I try to implement a layout like below image.
in this layout first ViewPager has fix height and second Viewpager contain RecyclerView.
How can connect scroll RecyclerView in Viewpager to NestedScrollView in parent?
I try this:
nestedScrollView.isFillViewport = true but RecyclerView scroll from top of Viewpager.
I have faced this issue some time ago. Where you want RecyclerView to be Scrolled by NestedScrollView. And nestedScrollingEnabled will not help you because RecyclerView is inside ViewPager.
Solution You can customize the ViewPager to resize the ViewPager to it's current page size on page swipe from this answer.
You can use the following code:
public class WrapContentViewPager extends ViewPager {
private int mCurrentPagePosition = 0;
public WrapContentViewPager(Context context) {
super(context);
}
public WrapContentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
try {
boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST;
if (wrapHeight) {
View child = getChildAt(mCurrentPagePosition);
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
}
}
} catch (Exception e) {
e.printStackTrace();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void reMeasureCurrentPage(int position) {
mCurrentPagePosition = position;
requestLayout();
}
}
Declare it in xml:
<your.package.name.WrapContentViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</your.package.name.WrapContentViewPager>
After that call reMeasureCurrentpage function on page swipe.
final WrapContentViewPager wrapContentViewPager = (WrapContentViewPager) findViewById(R.id.view_pager);
wrapContentViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
wrapContentViewPager.reMeasureCurrentPage(wrapContentViewPager.getCurrentItem());
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Also set android:nestedScrollingEnabled="false" to your RecyclerView.
Set these line on your RecyclerView in XML
android:nestedScrollingEnabled="false"
android:height="wrap_content"
Make your layout like this will work

Problems using FragmentStatePagerAdapter, Viewpager inside Scrollview

I am using:
An activity layout containing fragment added programmatically.
Parent fragment has FragmentStatePagerAdapter with view pager, This all content is inside ScrollView.
View pager is filled with some child fragments which has Recyclerview.
Issues are:
View pager fragment has a list, so I have to programmatically set parent view pager height. But I can't do that.
For that, I have used
viewpager.getLayoutParams().height = 20000;
viewpager.requestLayout();`
and
ViewGroup.LayoutParams params = viewPagerBottom.getLayoutParams();
params.height = 20000;
viewPagerBottom.setLayoutParams(params);
Also, I have tried view pager and view pager fragments height property as wrap_content
Can't see view pager content if i dont set scrollview android:layout_height="match_parent" with android:fillViewport="true".
It is parent fragment layout.xml.
<ScrollView
style="#style/scrollDefaultStyle"
android:layout_height="wrap_content"
android:fillViewport="true"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TabLayout .... />
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
</ScrollView>
You can customize the ViewPager to resize the ViewPager to it's current page size on page swipe from this answer.
You can use the following code:
public class WrapContentViewPager extends ViewPager {
private int mCurrentPagePosition = 0;
public WrapContentViewPager(Context context) {
super(context);
}
public WrapContentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
try {
boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST;
if (wrapHeight) {
View child = getChildAt(mCurrentPagePosition);
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
}
}
} catch (Exception e) {
e.printStackTrace();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void reMeasureCurrentPage(int position) {
mCurrentPagePosition = position;
requestLayout();
}
}
Declare it in xml:
<your.package.name.WrapContentViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</your.package.name.WrapContentViewPager>
After that call reMeasureCurrentpage function on page swipe.
final WrapContentViewPager wrapContentViewPager = (WrapContentViewPager) findViewById(R.id.view_pager);
wrapContentViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
wrapContentViewPager.reMeasureCurrentPage(wrapContentViewPager.getCurrentItem());
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Note: There could be hundreds of rows in ListView. It's not good idea to use wrap_content for ListView. Either you need to give fixed height for the ListView or else you need to use match_parent.

RecyclerView within ViewPager within NestedScrollView within CoordinatorLayout not scrollable

I got the following structure:
<CoordinatorLayout>
<AppBar>
<CollapsingToolbar
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"/>
</AppBar>
<NestedScrollView
android:layout_height="wrap_content"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<ViewPager />
</NestedScrollView>
</CoordinatorLayout>
The fragment inside the ViewPager looks like:
<LinearLayout
android:layout_height="wrap_content">
<RecyclerView
android:layout_height="wrap_content" />
</LinearLayout>
Inside this Fragment's RecyclerView, I got
<RelativeLayout
android:layout_height="wrap_content">
<...>
<RecyclerView
....
android:layout_height="wrap_content" />
</RelativeLayout>
Now the problem is, that the Toolbar gets collapsed correctly when I scroll the List below. But when the Toolbar is fully collapsed, no more scrolling is happening and I can't figure out how to achieve that.
For every RecyclerView, I am using a LinearLayoutManager with AutoMeasureEnabled set to true. Furthermore, HasFixedSize-Flags are set to false.
Any ideas?
//Edit: the content is not fixed; it gets passed in via reactiveUI.
You have to make view pager with dynamic height, I use below custom view pager inside NestedScrollView,
public class CustomPager extends ViewPager {
private View mCurrentView;
public CustomPager(Context context) {
super(context);
}
public CustomPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mCurrentView == null) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
int height = 0;
mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = mCurrentView.getMeasuredHeight();
if (h > height) height = h;
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void measureCurrentView(View currentView) {
mCurrentView = currentView;
requestLayout();
}
public int measureFragment(View view) {
if (view == null)
return 0;
view.measure(0, 0);
return view.getMeasuredHeight();
}
}
and Override below method into your FragmentStatePagerAdapter or FragmentPagerAdapter
private int mCurrentPosition = -1;
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
if (position != mCurrentPosition) {
Fragment fragment = (Fragment) object;
CustomPager pager = (CustomPager) container;
if (fragment != null && fragment.getView() != null) {
mCurrentPosition = position;
pager.measureCurrentView(fragment.getView());
}
}
}
CollapsingToolbar layout scroll set this propety
app:layout_scrollFlags="scroll|exitUntilCollapsed"
make changes like this , this will work
<CoordinatorLayout>
<AppBar>
<CollapsingToolbar
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"/>
</AppBar>
<ViewPager
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</CoordinatorLayout>
and in your fragments layout take parent as NestedScrollView and it'll work.

SwipeRefreshLayout with vertical view pager to only refresh on the topmost fragment

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) {
}};

disable swiping between tabs in FragmentActivity

I have a (Sherlock)FragmentActivity with 2 tabbed fragments. The left fragment is a GridView that displays pictures of an album and the right fragment consists of a ViewPager that is used to view individual pictures. From the left fragment you can scroll through the pictures and select one. Tabbing (or swiping) over to the right fragment will show the picture and because it is a ViewPager you can swipe to the preceding or the next picture.
This works great except that the FragmentActivity wants to intercept the right swipe and move back to the left tab. I would like to prevent the FragmentActivity from intercepting the swipes when I am on the right tab. If I had to disable swiping between tabs altogether it would be satisfactory. I just want the swiping to be dedicated to the current tab and not be used to move between tabs.
The following images indicate the current behavior. The right image shows what happens when I do a swipe to the right. As you can see the left tab starts to appear. I want the swipe to instead apply to the right tab only so that I can swipe between the images without the left tab appearing.
I see solutions to control swiping within a ViewPager but have yet to find a solution to control swiping between tabbed fragments.
Here is the xml for the GridView fragment and the ViewPager fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<FrameLayout android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="100dip"
android:gravity="center"
android:horizontalSpacing="4dip"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:verticalSpacing="4dip" />
</FrameLayout>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="1"/>
</LinearLayout>
Here a code summary of the ViewPager fragment:
public class FragmentFlash extends SherlockFragment {
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
private ViewPager pager = null;
private int pagerPosition;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pagerPosition = 0;
// Gesture detection
gestureDetector = new GestureDetector(new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.flash, container, false);
pager = (ViewPager) v.findViewById(R.id.pager);
pager.setOnTouchListener(gestureListener);
return v;
}
class MyGestureDetector extends SimpleOnGestureListener {
private static final int SWIPE_MIN_DISTANCE = 10;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 50;
#Override
public boolean onDown(MotionEvent e) {
return true;//false; make onFling work with fragments
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
else
// right to left swipe
if(distanceX > SWIPE_MIN_DISTANCE) {
if (pagerPosition < imageUrls.length-1)
pager.setCurrentItem(++pagerPosition);
// left to right swipe
} else if (distanceX < -SWIPE_MIN_DISTANCE) {
if (pagerPosition > 0)
pager.setCurrentItem(--pagerPosition);
}
return true;
} catch (Exception e) {
// nothing
}
return false;
}
}
private class ImagePagerAdapter extends PagerAdapter {
private String[] images;
private LayoutInflater inflater;
ImagePagerAdapter(String[] images) {
this.images = images;
inflater = mContext.getLayoutInflater();
}
#Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
#Override
public void finishUpdate(View container) {
}
#Override
public int getCount() {
return images.length;
}
#Override
public Object instantiateItem(View view, int position) {
final View imageLayout = inflater.inflate(R.layout.item_pager_image, null);
final ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image);
final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading);
byte[] image = ;//get byte array from file at images[position];
if (null != image) {
Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
imageView.setImageBitmap(bitmap);
}
((ViewPager) view).addView(imageLayout, 0);
return imageLayout;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
#Override
public Parcelable saveState() {
return null;
}
#Override
public void startUpdate(View container) {
}
}
public void pagerPositionSet(int pagerPosition, String[] imageUrls) {
Log.i(Flashum.LOG_TAG, "FragmentFlash pagerPositionSet: " + pagerPosition);
if (pagerPosition >= 0)
this.pagerPosition = pagerPosition;
if (pager != null) {
pager.setAdapter(new ImagePagerAdapter(imageUrls));
pager.setCurrentItem(this.pagerPosition);
}
}
}
This is the item_pager_image.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="1dip" >
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:contentDescription="#string/descr_image" />
<ProgressBar
android:id="#+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
Ok, I finally figured this out. Laurence Dawson was on the right track but instead of applying the CustomViewPager to the fragment it needs to be applied to the FragmentActivity. You see, switching between tabs, which is managed by the activity, is also a ViewPager adaptor. Thus, xml for the activity is
<TabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="#android:id/tabs"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"/>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"/>
<com.Flashum.CustomViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</TabHost>
And the custom ViewPager is as suggested except that that the constructor enables it to cause onInterceptTouchEvent to return false. This prevents the FragmentActivity from acting on the swipe so that it can be dedicated to the fragment!
public class CustomViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = **false**;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
You need to override the onInterceptTouchEvent method for your ViewPager, you can do this by extending ViewPager or visit this link for a great tutorial on adding this:
http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html

Categories

Resources