Размах виджета не работает после изменения фрагмента динамически - PullRequest
0 голосов
/ 15 апреля 2019

Проблема возникает, когда я пытаюсь динамически переключать (не заменять с помощью FragmentTransaction) фрагмент в viewpager. Этот просмотрщик находится внутри другого просмотрщика, но это не проблема. Он использует ViewPagerStateAdapter, который также отлично работает.

Теперь, когда этот родительский фрагмент Viewpager открыт, функция свайпа отключена. Должен быть выполнен один метод, который приводит к разблокировке свайпа.

Перелистывание между фрагментами работает хорошо, плавно и быстро, когда я выполняю этот конкретный метод при нажатии кнопки.

Но когда этот же метод выполняется автоматически из результата асинхронной задачи, который выполняется из onCreateView (), это приводит к неправильной прокрутке (очень медленно, трудно провести к следующему / предыдущему фрагменту).

Это адаптер пейджера:

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, который выполняет asynctask, который в результате выполняет метод, который затем приводит к разблокировке пролистывания

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

Это не помогло.

1 Ответ

0 голосов
/ 15 апреля 2019

Оказалось, что 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;
}
...