【问题标题】:Viewpager swipe aint working after change fragment dynamically动态更改片段后,Viewpager 滑动不起作用
【发布时间】:2019-04-15 01:57:59
【问题描述】:

当我尝试在 viewpager 中动态切换(不是使用 FragmentTransaction 替换)片段时出现的问题。 此视图分页器位于其他视图分页器内,但这不是问题。 它使用 ViewPagerStateAdapter 也可以正常工作。

现在,当这个 viewpager 父片段打开时,滑动功能被关闭。必须执行一种方法,这会导致滑动被解锁。

当我在按钮单击时执行此特定方法时,片段之间的滑动效果很好,流畅且快速。

但是,当从 onCreateView() 执行的 asynctask 结果自动执行相同的方法时,会导致滑动混乱(非常慢,难以滑动到下一个/上一个片段)。

这是寻呼机适配器:

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

片段是这样动态切换的:

public void switchPagerFragment(String fragmentTag) {
    pager.setCurrentItem(pagerAdapter.getPagePositionByTag(fragmentTag));
    pagerAdapter.notifyDataSetChanged();
}

这是viewpager中的第一个片段,它执行异步任务,结果执行方法,然后导致滑动解锁

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

这是我的自定义无滑动寻呼机:

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

当我在某个按钮单击侦听器中调用 updateSwipe() 时,一切正常。

我认为这可能与用户界面有关。 所以我把这个方法封装成这样:

public void updateSwipe(boolean working) {
    setupActivity().get().runOnUiThread(new Runnable() {
        swipeable = working;
        if (pager != null)
            pager.setSwipeable(swipeable);
    });
}

没用。

【问题讨论】:

  • 尝试使用FragmentPagerAdapter,并覆盖getItemId
  • 然后我的寻呼机出现故障并且即使没有动态更改页面也可以这样工作。抱歉,但我忘了提及这一点,我花了几天时间让这个寻呼机工作在说不是动态的(用户引导的)滑动中,这是唯一对我有用的解决方案(使用 FragmentStatePager)。
  • 请检查以下场景是否也适用:stackoverflow.com/questions/49046773/…
  • 我不确定到底检查了什么...当我从 android studio 运行应用程序,然后导航到此片段,然后单击主页按钮,然后终止应用程序,然后再次打开它再次运行...但它不再显示退出的相同片段...而是显示应用程序的第一个片段...我在 android 7 上测试

标签: android android-fragments android-asynctask android-viewpager


【解决方案1】:

原来fragment的onCreateView()调用executeTask()的地方不对。

应该从片段的 onAttach() 调用它。

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    if(pager != null)
        pager.setSwipeable(swipeable);

    executeTask();
}

/**
 * Set the callback to null so we don't accidentally leak the
 * Activity instance.
 */
@Override
public void onDetach() {
    super.onDetach();

    if (task != null && task.getStatus() == AsyncTask.Status.RUNNING)
        task.cancel(true);
    task = null;
}

【讨论】:

    猜你喜欢
    • 2013-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    • 2016-11-03
    • 2019-10-05
    • 2015-12-03
    • 1970-01-01
    相关资源
    最近更新 更多