Жест смахивания применяется на уровне фрагмента вместе с ViewPager с отключенным по умолчанию смахиванием

Я нашел вопрос ниже: Android: FragmentActivity внутри FragmentActivity (ScrollView в NavigationBar). Однако этот мой вопрос касается того, как использовать транзакции для отображения фрагментов, а также включить безопасное обнаружение жестов смахивания. Примечание. В опубликованном мною ответе есть ссылка (здесь также есть эффективный способ отображения фрагментов в контейнере с использованием транзакций, включая два сценария). Пожалуйста, посмотри на это. Я пробовал несколько вещей в этом отношении, но используя фрагмент, поддерживающий ViewPager, а не вложенный:

Подробности: https://moqups.com/[email protected]/lc0ZOERO/p:a5d7b55eb

  1. Отключено смахивание по умолчанию с использованием onTouchEvent и onInterceptTouchEvent с использованием настраиваемого ViewPager.
  2. Объявленный FragmentStatePagerAdapter снабжен списком фрагментов, каждый из которых отображается на каждой вкладке.
  3. Объявите фрагменты в main_layout main_activity, рядом с которым находится ViewPager. Идея состоит в том, чтобы отображать activity_fragments, когда нажимается кнопка на ViewPager_fragment и когда пользователь нажимает кнопку возврата, тогда ViewPager_fragment по умолчанию снова отображается с использованием транзакций заднего стека при добавлении и выталкивании их на BackPressed активности. Поэтому я также поддерживаю свой собственный задний стек, чтобы отображать / скрывать activity_fragments, когда задний стек выводит транзакцию.

Теперь я хочу выполнить третий пункт выше, используя жесты смахивания только вправо [слева направо].

Для этого я использовал GestureListener и SimpleOnGestureListener, а также OnTouchEvent активности.

Проблема, с которой я сталкиваюсь:

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

  1. В области фрагмента, в макете которой есть несколько представлений.
  2. Только в направлении влево-вправо.
  3. Только от activity_fragment до фрагмента вкладки ViewPager, чтобы вести себя как навигация по истории, как это уже было сделано в реализации onBakPressed / onKeyDown с использованием всплывающих окон заднего стека и моего настраиваемого заднего стека.

Я попробовал следующий класс и изменил фрагмент своей деятельности в таких макетах.

Слушатель My Gesture and Touch расширен макетом кадра:

        public class OnSwipeTouchListener extends FrameLayout {

        private final GestureDetector gestureDetector;
        private static final String TAG = "OnSwipeTouchListener";
    private Context context;
        public OnSwipeTouchListener(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context=context;
            gestureDetector = new GestureDetector(context, new GestureListener());
            setClickable(true);

        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            return super.onInterceptTouchEvent(ev);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
 gestureDetector.onTouchEvent(motionEvent);
            return super.onTouchEvent(event);
        }


        private final class GestureListener extends SimpleOnGestureListener {

            private static final int SWIPE_THRESHOLD = 100;
            private static final int SWIPE_VELOCITY_THRESHOLD = 100;

            @Override
            public boolean onDown(MotionEvent e) {

                return true;
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

                boolean result = false;
                try {
                    float diffY = e2.getY() - e1.getY();
                    float diffX = e2.getX() - e1.getX();
                    if (Math.abs(diffX) > Math.abs(diffY)) {
                        if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                            if (diffX > 0) {
                                onSwipeRight();
                            } else {
                                onSwipeLeft();
                            }
                        }
                    } else {
                        if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) >           SWIPE_VELOCITY_THRESHOLD) {
                            if (diffY > 0) {
                                onSwipeBottom();
                            } else {
                                onSwipeTop();
                            }
                        }
                    }
                } catch (Exception exception) {
                    //see that e1 is null
                }
                return result;
            }
        }

        public void onSwipeRight() {
            ///manage my back stack history here.
        }

        public void onSwipeLeft() {
        }

        public void onSwipeTop() {
        }

        public void onSwipeBottom() {
        }
    }

а затем измените макеты фреймов на эту ссылку на класс:

<path.to.my.package.OnSwipeTouchListener
            android:id="@+id/activity_frag_frame_layout1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:visibility="invisible" >

            <fragment
                android:id="@+id/activity_frag1"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                class="path.to.my.package.fragments.Activity_Frag1"
                android:tag="act_frag1" />
        </path.to.my.package.OnSwipeTouchListener>

Мне это мало помогло, так что должно помочь вам в поиске решения. В одном из фрагментов перестал работать searchView, и ни один клик не работает. Если вы получили то, чего я хочу достичь, пожалуйста, помогите в этом отношении.

Обновление 1: возврат true как в onTouchEvent, так и в onInterceptTouchEvent имеет желаемый эффект, но он блокирует щелчки во фрагментах, где есть SearchView, ни один щелчок не работает в представленных интерактивных представлениях. Только свайп работает. Обновление: в моем последнем: я также полностью отказался от использования стеков транзакций назад, потому что я полагаюсь на свой собственный задний стек, в котором я поддерживаю историю навигации для всех вкладок. Для этого я использую методы setCurrentTab и onTabSelected, предоставленные ViewPager и FragmentStatePagerAdapter.

Обновление 2: это сложно реализовать: проверьте, какие события нужно перехватить, а какие передать дочерним представлениям: http://developer.android.com/training/gestures/viewgroup.html

Обновление 3:

  1. В моем макете для активности есть пейджер просмотра, а в макете каждого кадра под ним есть один фрагмент.

  2. Когда вы запускаете приложение, ViewPager показывает фрагмент на первой вкладке.

  3. Когда нажимается кнопка на этом фрагменте, отображается один из фрагментов в макете фрейма под пейджером просмотра и добавляется в мой собственный задний стек.

  4. При нажатии клавиши возврата этот фрагмент снова скрывается, чтобы показать фрагмент вкладки в пейджере просмотра. Все вышеперечисленное выполнено. Только я хочу, чтобы срабатывал жест смахивания слева направо, и я обнаружил, что могу делать это, перехватывая события касания. Но он этого совсем не делает. Когда я возвращаю true, работает только жест смахивания, в противном случае это действие отменяется и щелчки по этому фрагменту работают.


person Abhinav Saxena    schedule 16.09.2013    source источник
comment
@AliImran Уточнение: что, если вам нужно больше фрагментов, кроме фрагментов вкладок (которые вы показываете на вкладках), потому что, когда вы нажимаете кнопку на этом фрагменте, вы хотите показать другой фрагмент, а не новое действие, потому что вы хотите чтобы вкладки и панель действий отображались и пользователь чувствовал, что этот новый фрагмент был открыт на той же вкладке, поскольку он будет занимать то же место, что и фрагмент вкладки. Это то, что я пытался сделать. Но теперь мне нужна функция смахивания, как описано выше.   -  person Abhinav Saxena    schedule 16.09.2013
comment
Я думаю, вы этого хотите: - github.com/astuetz/ViewPagerExtensions   -  person Ali Imran    schedule 16.09.2013
comment
объясните свою проблему с изображениями.   -  person Ali Imran    schedule 04.10.2013
comment
Я добавил мокуп (ссылка в вопросе). Доступ к дочерней странице, не покидая текущей вкладки. Новая страница связана с контекстом текущей вкладки. У человека должна быть привычка иметь книгу с графиками или блокнот, чтобы знать, о чем идет речь, если вопрос полностью в текстовой форме.   -  person Abhinav Saxena    schedule 02.06.2014


Ответы (1)


Я упомянул этот ответ в http://mobi-app-dev.blogspot.in/2014/01/android-transactions.html.

Проверьте, какие события необходимо перехватить, а какие передать дочерним представлениям: http://developer.android.com/training/gestures/viewgroup.html

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

@Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercepted = super.onInterceptTouchEvent(event);

        // In general, we don't want to intercept touch events. They should be
        // handled by the child view.

        gestureDetector.onTouchEvent(event);
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean touched = super.onTouchEvent(event);
        gestureDetector.onTouchEvent(event);
        return touched;
    }

Вот несколько советов, которым я сейчас следую при использовании фрагментов в своей деятельности:

Эффективное управление транзакциями по фрагменту:

[Примечание: если вы используете FragmentStatePagerAdapter, вы можете поиграть с заменой фрагмента другим фрагментом по определенному индексу в списке фрагментов, которые вы используете в качестве данных для этого адаптера, таким образом, что вы находитесь на той же вкладке но его содержимое изменяется без изменения вкладки. Затем используйте notifyDataSetChanged (). Здесь вы не используете транзакции, но в остальном вы их используете].

  1. Используйте Fragment.instantiate () для инициализации ваших фрагментов вместо конструктора.
  2. Используйте слушателей для обновления / удаления ссылки экземпляра (из коллекции, используемой для их ссылки) фрагмента onCreateView и onDestroy.
  3. Используйте getView () для получения корневого представления фрагмента повсюду и при обновлении функциональности.
  4. Не отслеживайте экземпляры, по возможности избегайте статических указателей.
  5. Используйте getSupportFragment вместо сохранения ссылки на FragmentManager в адаптере пейджера просмотра или где-либо еще.
  6. Используйте привязку присоединения к скрытому представлению транзакции, чтобы избавиться от дочерних представлений в корневом представлении фрагмента и выполнить повторную инициализацию. Это связано с тем, что единовременно должен быть виден только один фрагмент, а остальные нужно отсоединять. Поэтому прикрепляйте заново по запросу.
  7. getActivity () или getApplicationContext () в зависимости от того, что применимо, вместо сохранения глобальной переменной для хранения ссылок на контекст.
  8. onConfiguration change (ориентация, клавиатура, изменение размера): выполнить в действии и передать его активному фрагменту, который им управляет. Важно: если вы действительно хотите использовать фрагменты для транзакций, не объявляйте их в макетах. Укажите идентификатор контейнера (макета) в транзакции добавления фрагмента.
  9. Фрагментная транзакция должна выполняться в вызове события, а не где-либо еще, и такое событие не должно повторяться. Это предотвращает исключение недопустимого аргумента.
  10. Существует метод ViewPager, в котором вам не нужно использовать фрагменты. Вместо этого вы можете использовать Views или ViewGroups. Это заменяет вложение фрагментов.
  11. Определите уровень фрагментов, это означает, что если вы хотите, чтобы фрагмент «B» заменил существующий фрагмент «A», и когда вы хотите вернуться, чтобы показать фрагмент «A» при повторном нажатии на «B», поместите эту транзакцию обратно куча.

Совет: будьте осторожны при добавлении функции смахивания, потому что есть другие интерактивные представления. Проведите пальцем с перехватом касания на RootView, возвращающем false, но анализируя касания.


Еще одна вещь: вы должны заметить, что наличие одного фрагмента в одном контейнере одновременно решает другую проблему: если есть два фрагмента, один поверх другого, щелчки от одного фрагмента переходят к другому фрагменту, который находится ниже. Так что скрывайте или заменяйте, чтобы иметь только один фрагмент за раз. Back-Stack помогает поддерживать уровни навигации, а при изменении или обновлении конфигурации попробуйте обновить один и тот же экземпляр целевого активного фрагмента вместо выполнения транзакций, поскольку это изменяет порядок перемещаемых фрагментов.

person Abhinav Saxena    schedule 13.03.2014