user interface - Android: ViewPager gets stuck in between views -
i have viewpager swipes between fragments. i'm using fragmentstatepageradapter feed fragments viewpager. if user swipes left @ normal pace, , swipes right quickly, can viewpager weird state shows multiple fragments.
for example, if user on fragment a, swipes left fragment b @ normal pace, , swipes right go fragment a, on screen shows both fragments & b.
anybody have ideas on why happening or way prevent it?
here's looks like:
here's viewpager definition in xml:
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.company.views.customactionbar android:id="@+id/customactionbar" android:layout_width="match_parent" android:layout_height="@dimen/height_actionbar" android:layout_alignparenttop="true"/> <android.support.v4.view.viewpager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/customactionbar"/>
also, logged output onpagechangelistener() , noticed when viewpager gets stuck in between views, it's reporting positionoffset of 0. here's viewpager's values transitions state_dragging state_settling state_idle when lands in weird state:
state = 0 prevstate: 2 position: 1 positionoffset: 0.0
state = 1 prevstate: 0 position: 1 positionoffset: 0.0
state = 2 prevstate: 1 position: 1 positionoffset: 0.4069444
state = 0 prevstate: 2 position: 2 positionoffset: 0.0
so appears if viewpager reporting wrong positionoffset me.
full sample code activity , adapter:
public class activitybagelprofileviewer extends customabstractfragmentactivity implements customactionbarcontract, listenerprogress, listenersync { public static final string extra_bagel_index = "bagel"; public static final int request_code_bagel_profile_viewer = 4000; public static final int result_go_to_pass_flow = 12; public static final int result_go_to_like_flow = 14; public static final int result_go_to_see_more_bagels = 16; private viewpager mprofilesviewpager; private customactionbar mcustomactionbar; private int mviewpagerposition; private dialogprogress mdialogprogress; private bagelviewpageradapter madapterbagelviewpager; private list<bagel> mlistbagels; @override protected void oncreate(bundle savedinstancestate) { logger.d("enter"); super.oncreate(savedinstancestate); if (managergive.is_branch_session_open == false) { managergive.initializebranchmetricssession(); } setcontentview(r.layout.activity_with_viewpager); mcustomactionbar = (customactionbar) findviewbyid(r.id.customactionbar); mcustomactionbar.setmenu(this); mprofilesviewpager = (viewpager) findviewbyid(r.id.viewpager); if (getintent().getextras() != null) { mviewpagerposition = getintent().getextras().getint(extra_bagel_index, 0); } } @override protected void onstop() { super.onstop(); managergive.closebranchmetricssession(); } public void oniconclick(view view) { logger.d("enter"); finishwithanimation(); } private void finishwithanimation() { setresult(result_ok); finish(); overridependingtransition(r.anim.slide_in_from_left, r.anim.slide_out_to_right); } @override public void onbackpressed() { if (!super.handlebackpressedevent()) { finishwithanimation(); } } private void setupnewadapter() { mlistbagels = bakery.getinstance().getmanagerbagel().getcopyofbagelswithoutcurrent(); madapterbagelviewpager = new bagelviewpageradapter(getsupportfragmentmanager(), mlistbagels, this); mprofilesviewpager.setadapter(madapterbagelviewpager); mprofilesviewpager.setonpagechangelistener(new viewpager.onpagechangelistener() { @override public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) { } @override public void onpageselected(int position) { setactionbar(position); mviewpagerposition = position; } @override public void onpagescrollstatechanged(int state) { } }); mprofilesviewpager.setcurrentitem(mviewpagerposition, false); } @override protected void onresume() { logger.d("enter"); super.onresume(); bakery.getinstance().getmanagersyncdata().addlistener(this); if (mprofilesviewpager.getadapter() == null) { logger.d("adapter null. setting new adapter"); setupnewadapter(); } else { if (mprofilesviewpager.getadapter().getcount() != bakery.getinstance().getmanagerbagel().getcopyofbagelswithoutcurrent().size()) { logger.d("bagel list in bakery changed size. setting new adapter"); setupnewadapter(); } } if (mlistbagels.size() > 0) { setactionbar(mviewpagerposition); mdialogprogress = new dialogprogress(this); } else { //kv has gone terribly wrong if don't have bagels, finish finish(); } } private void setactionbar(int bagelindex) { logger.d("bagelindex=" + bagelindex); bagel bagel = mlistbagels.get(bagelindex); //kv if our current bagel , haven't taken action yet, show timer if (bakery.getinstance().getmanagerbagel().getcurrentbagel() == bagel && bagel.getaction() != bagel.action_liked && bagel.getaction() != bagel.action_passed) { logger.d("setting #timer in action bar"); mcustomactionbar.starttimelefttimer(dateutils.getmillisfromutc(bagel.getenddate()), this, new listenertimer() { @override public void ontimerexpired() { logger.d("enter"); bakery.getinstance().getmanagersyncdata().performsync(null, false); } }, mcustomactionbar.gettextviewtimeleft(), r.string.timer_blank); mcustomactionbar.setlabel(r.string.time_left); mcustomactionbar.hidetitle(); } //kv otherwise show date else { mcustomactionbar.settitle(dateutils.getlocalizeddatefromstringdate(bagel.getstartdate(), dateutils.date_with_time_pattern)); mcustomactionbar.stoptimelefttimer(); mcustomactionbar.hidetimeleft(); } } @override protected void onsaveinstancestate(bundle outstate) { super.onsaveinstancestate(outstate); outstate.putint(extra_bagel_index, mviewpagerposition); } @override protected void onrestoreinstancestate(bundle savedinstancestate) { logger.d("enter"); super.onrestoreinstancestate(savedinstancestate); if (savedinstancestate.containskey(extra_bagel_index)) { mviewpagerposition = savedinstancestate.getint(extra_bagel_index); } } @override protected void onactivityresult(int requestcode, int resultcode, intent data) { super.onactivityresult(requestcode, resultcode, data); logger.d("requestcode=" + requestcode + ", resultcode=" + resultcode + ", data=" + data); switch (requestcode) { case activitybeanshop.request_code: if (resultcode == activity.result_ok && data != null) { //fp user purchased sufficient beans resume transaction purchasetype interruptedpurchasetype = (purchasetype) data.getserializableextra(activitybeanshop.extra_purchase_type); switch (interruptedpurchasetype) { case bonus_bagel: case open_sesame: case rematch: bundle bundle = new bundle(); bundle.putserializable(managerpurchase.extra_purchase_type, interruptedpurchasetype); managerevents.notifylisteners(eventtype.bean_transaction_for_feature_unlock_complete, bundle); logger.d("notified listeners #purchase bean transaction, can resume feature #purchase"); break; default: logger.w("unrecognized purchase type: " + interruptedpurchasetype.getitemname()); } } break; default: logger.w("could not recognize code: " + requestcode); } } @override public int gettitleid() { return r.string.bagel_action_checked; } @override public int geticonid() { return r.drawable.selector_icon_up; } @override public void showprogress(int stringid) { mdialogprogress.settext(stringid); mdialogprogress.show(); } @override public void dismissprogress() { viewutils.safelydismissdialog(mdialogprogress); } public void setactionbar() { setactionbar(mviewpagerposition); } @override public void onsynccomplete() { logger.d("enter"); mlistbagels = bakery.getinstance().getmanagerbagel().getcopyofbagelswithoutcurrent(); madapterbagelviewpager.setbagels(mlistbagels); } public boolean isshowingthisbagel(bagel bagel) { bagel currentlyshownbagel = mlistbagels.get(mviewpagerposition); return bagel == currentlyshownbagel; } private static class bagelviewpageradapter extends fragmentstatepageradapter { private list<bagel> mbagels; private listenerprogress mlistenerprogress; public bagelviewpageradapter(fragmentmanager fragmentmanager, list<bagel> bagels, listenerprogress listenerprogress) { super(fragmentmanager); logger.d("bagels=" + bagels); this.mbagels = bagels; mlistenerprogress = listenerprogress; } @override public fragment getitem(int i) { logger.d("i=" + i); userprofile myprofile = bakery.getinstance().getmanageruserprofile().getmyownprofile(); fragmentprofile fragment = fragmentprofile.newinstance(mbagels.get(i), false, myprofile); fragment.setlistenerprogress(mlistenerprogress); return fragment; } @override public int getcount() { return mbagels.size(); } public void setbagels(list<bagel> bagels) { mbagels = bagels; notifydatasetchanged(); } } }
and here's xml layout code layout of each fragment (had cut out b/c of char limit):
<?xml version="1.0" encoding="utf-8"?> <scrollview xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/scrollview"> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="-0.5dp" android:orientation="vertical" android:animatelayoutchanges="true" android:id="@+id/profile_top_container"> <!-- photos section pager/carousel --> <framelayout android:id="@+id/photoviewpagercontainer" android:layout_width="match_parent" android:layout_height="wrap_content"> <com.coffeemeetsbagel.views.customasshitviewpager android:id="@+id/pager_profile_images" xmlns:android="http://schemas.android.com/apk/res/android" app:aspectratio="@integer/photo_ratio_height_over_width" android:layout_width="match_parent" android:layout_height="wrap_content"/> <linearlayout android:id="@+id/linearlayout_bulletsandfriendscontainer" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="bottom"> <com.coffeemeetsbagel.views.customtextview android:id="@+id/textview_stamp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="invisible" app:customfont="raleway-bold.ttf" android:layout_gravity="end" android:textsize="@dimen/text_stamp" android:paddingtop="@dimen/margin_large" android:layout_marginend="@dimen/margin_xxxxxsmall" android:layout_marginright="@dimen/profile_margin_smaller"/> <!-- photo circle indicators --> <com.viewpagerindicator.circlepageindicator android:id="@+id/bullet_indicators" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginbottom="@dimen/circle_indicator_margin_bottom" android:clickable="false" app:fillcolor="@color/blue_cmb" app:pagecolor="@color/gray_background" app:radius="@dimen/circle_indicator_radius" app:strokewidth="0dp"/> <!-- container mutual friends strip --> <relativelayout android:id="@+id/relativelayout_mutual_friends_container" android:layout_width="match_parent" android:layout_height="@dimen/baseline_grid_component_touchable" android:background="@color/white_transparent" android:visibility="gone"> <com.coffeemeetsbagel.views.customtextview android:id="@+id/textview_mutual_friends_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentstart="true" android:layout_alignparentleft="true" style="@style/profile_mutual_friends_text"/> <linearlayout android:id="@+id/linearlayout_mutual_friends_icons" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" android:layout_alignparentend="true" android:layout_alignparentright="true" android:layout_marginend="@dimen/baseline_grid_small" android:layout_marginright="@dimen/baseline_grid_small" android:layout_centervertical="true"> <imageview android:id="@+id/imageview_icon0" android:layout_width="@dimen/baseline_grid_component_touchable" android:layout_height="@dimen/baseline_grid_component_touchable" android:padding="@dimen/typography_smallest" android:background="@color/transparent" android:visibility="gone"/> <imageview android:id="@+id/imageview_icon1" android:layout_width="@dimen/baseline_grid_component_touchable" android:layout_height="@dimen/baseline_grid_component_touchable" android:background="@color/transparent" android:padding="@dimen/typography_smallest" android:visibility="gone"/> <imageview android:id="@+id/imageview_icon2" android:layout_width="@dimen/baseline_grid_component_touchable" android:layout_height="@dimen/baseline_grid_component_touchable" android:background="@color/transparent" android:padding="@dimen/typography_smallest" android:visibility="gone"/> </linearlayout> </relativelayout> </linearlayout> </framelayout> <!-- buttons section user actions pass / like--> <linearlayout android:id="@+id/linearlayout_buttons_pass_like" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginbottom="@dimen/baseline_grid_smaller" android:layout_marginleft="@dimen/baseline_grid_small" android:layout_marginright="@dimen/baseline_grid_small" android:layout_margintop="@dimen/baseline_grid_medium" android:orientation="horizontal" android:visibility="gone"> <imageview android:id="@+id/button_pass" android:layout_width="0dp" android:layout_height="@dimen/profile_action_button_height" android:layout_weight="1" android:background="@drawable/ripple_button_pass" android:clickable="true" android:src="@drawable/icon_pass_pressed" android:scaletype="center" android:layout_marginright="@dimen/margin_small"/> <imageview android:id="@+id/button_like" android:layout_width="0dp" android:layout_height="@dimen/profile_action_button_height" android:layout_weight="1" android:background="@drawable/ripple_button_like" android:clickable="true" android:src="@drawable/icon_like_pressed" android:scaletype="center" android:layout_marginleft="@dimen/margin_small"/> </linearlayout> <!-- buttons section user actions rematch / give--> <linearlayout android:id="@+id/linearlayout_buttons_rematch_give" android:layout_width="match_parent" android:layout_height="@dimen/give_ten_button_height" android:layout_marginbottom="@dimen/baseline_grid_smaller" android:layout_marginleft="@dimen/baseline_grid_small" android:layout_marginright="@dimen/baseline_grid_small" android:layout_margintop="@dimen/baseline_grid_medium" android:orientation="horizontal" android:gravity="center" android:visibility="gone"> <com.coffeemeetsbagel.views.customtextview android:id="@+id/textview_rematch" android:layout_width="@dimen/zero_dip" android:layout_height="match_parent" android:layout_marginright="@dimen/give_take_button_margin_side" android:layout_weight="1" style="@style/button_give_take_rematch" android:text="@string/rematch"/> <com.coffeemeetsbagel.views.customtextview android:id="@+id/text_view_give_with_rematch" android:layout_width="@dimen/zero_dip" android:layout_weight="1" android:layout_height="match_parent" style="@style/button_give_take_rematch" android:text="@string/give"/> </linearlayout> <com.coffeemeetsbagel.views.customtextview android:id="@+id/textview_they_like_you" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableleft="@drawable/icon_like_alert" android:drawablepadding="@dimen/margin_xxsmall" style="@style/profile_info_item_value" android:layout_marginleft="@dimen/margin_med" android:paddingtop="@dimen/baseline_grid_smaller"/> <viewstub android:id="@+id/viewstub_profile_feedback" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout="@layout/profile_feedback"/> <!-- profile information table --> <!-- name --> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:paddingtop="@dimen/baseline_grid_smaller" android:orientation="horizontal"> <com.coffeemeetsbagel.views.customtextview android:text="@string/profile_info_label_name" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/> <com.coffeemeetsbagel.views.customtextview android:id="@+id/profile_info_value_name" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </linearlayout> <!-- age --> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.customtextview android:text="@string/profile_info_label_age" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.customtextview android:id="@+id/profile_info_value_age" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </linearlayout> <!-- location --> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.customtextview android:text="@string/location" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.customtextview android:id="@+id/profile_info_value_location" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </linearlayout> <!-- ethnicity --> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.customtextview android:text="@string/profile_info_label_ethnicity" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.customtextview android:id="@+id/profile_info_value_ethnicity" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </linearlayout> <!-- height --> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.customtextview android:text="@string/profile_info_label_height" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.customtextview android:id="@+id/profile_info_value_height" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </linearlayout> <!-- religion --> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.customtextview android:text="@string/profile_info_label_religion" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.customtextview android:id="@+id/profile_info_value_religion" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </linearlayout> <!-- occupation --> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.customtextview android:text="@string/profile_info_label_occupation" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.customtextview android:id="@+id/profile_info_value_occupation" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </linearlayout> <!-- employer --> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal">
...
i've noticed see issue if have animations given animatelayoutchanges. deactivating in xml file, prevents pages stuck in middle.
Comments
Post a Comment