The problem I have occurs when I try to dynamically switch (not replace using FragmentTransaction) fragment in viewpager. This viewpager is inside other viewpager but this is not a problem. It uses ViewPagerStateAdapter which also works fine.
Now when this viewpager parent fragment is opened, the swipe functionality is turned off. One method has to be executed, which results in swipe being unlocked.
Swipe between fragments works well, smooth and fast when I execute this specific method on button click.
But when this same method is executed autodynamically from asynctask result, which is executed from onCreateView(), it results in swipe messed up (very slow, hard to swipe to next/prev fragment).
This is pager adapter:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<ABaseFragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
private final List<String> mFragmentTagList = new ArrayList<>();
private WeakReference<Context> context;
private int pagerID;
private FragmentManager fragmentManager;
private int previous = 0;
public ViewPagerAdapter(FragmentManager manager, int pagerID, Context ctx) {
super(manager);
this.pagerID = pagerID;
this.fragmentManager = manager;
this.context = new WeakReference<>(ctx);
}
public ViewPagerAdapter(FragmentManager manager, int pagerID) {
super(manager);
this.pagerID = pagerID;
this.fragmentManager = manager;
}
@Override
public ABaseFragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getItemPosition(@NonNull Object object) {
return POSITION_NONE;
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(ABaseFragment fragment, String title, String tag) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
mFragmentTagList.add(tag);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
public String getPageTag(int position) {
return mFragmentTagList.get(position);
}
public ABaseFragment getPageFragmentByPosition(int position) {
return mFragmentList.get(position);
}
public ABaseFragment getPageFragmentByTag(String fragTag) {
return mFragmentList.get(mFragmentTagList.indexOf(fragTag));
}
public int getPagePositionByTag(String fragmentTag) {
return mFragmentTagList.indexOf(fragmentTag);
}
public ABaseFragment getPageFragmentByClass(String fragClassName) {
if (fragClassName != null && !fragClassName.trim().isEmpty())
for (ABaseFragment pagerFragment : mFragmentList) {
if (pagerFragment.getClass().getName().trim().equals(fragClassName.trim()))
return pagerFragment;
}
return null;
}
public void onPageChanged(int position) {
// logic when viewpager page changes here...
previous = position;
}
}
This is how fragment is switched dynamically:
public void switchPagerFragment(String fragmentTag) {
pager.setCurrentItem(pagerAdapter.getPagePositionByTag(fragmentTag));
pagerAdapter.notifyDataSetChanged();
}
And this is the first fragment in viewpager, which executes asynctask, which in result executes the method which then results in swipe unlocked
public class ParamsFragment extends ABaseFragment implements IBackPressCallback {
/**
* This method will only be called once when the retained
* Fragment is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Retain this fragment across configuration changes.
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_params, container, false);
relativeDummy = (RelativeLayout) rootView.findViewById(R.id.layParamsDummy);
executeTask();
return rootView;
}
private void executeTask() {
DateRequest request = new DateRequest();
request.setParams(params);
task = new DateTask();
task.setResultHandler(callback);
task = (AbstractTask<DateRequest, DateResponse>) task
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, request);
}
public void updateSwipe(boolean working) {
// here try to unlock the swipe
swipeable = working;
if (pager != null)
pager.setSwipeable(swipeable);
}
// CALLBACKS
private TaskResultHandler<DateResponse> callback = new TaskResultHandler<DateResponse>() {
@Override
public void handle(final DateResponse result, final Exception ex) {
if (result != null) {
updateSwipe(true);
((MainActivity) setupActivity().get()).switchPagerFragment(Consts.TAG_FRAG_TOTALS);
} else
Toast.makeText(setupActivity().get(), "date task error", Toast.LENGTH_LONG).show();
}
};
}
And this is my custom swipeless pager:
public class SwipelessPager extends ViewPager {
private Boolean swipeable = true;
public SwipelessPager(Context context) {
super(context);
}
public SwipelessPager(Context context, AttributeSet attrs){
super(context,attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return swipeable ? super.onInterceptTouchEvent(event) : false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return swipeable ? super.onTouchEvent(event) : false;
}
@Override
public boolean canScrollHorizontally(int direction) {
return swipeable ? super.canScrollHorizontally(direction) : false;
}
public void setSwipeable(Boolean swipeable){
//When swipeable = false not work the scroll and when swipeable = true work the scroll
this.swipeable = swipeable;
}
public Boolean getSwipeable() {
return swipeable;
}
}
When I call updateSwipe() in some button click listener, everything works smooth and nice.
I thought that this might be related to user interface. So I enclosed this method like this:
public void updateSwipe(boolean working) {
setupActivity().get().runOnUiThread(new Runnable() {
swipeable = working;
if (pager != null)
pager.setSwipeable(swipeable);
});
}
It didnt help.