Использование setVisibility(View.INVISIBLE) с библиотекой Pre Lollipop Circular Reveal

Я работаю над проектом, в котором я хочу использовать эффект Circular Reveal в соответствии с Material Design. Проект имеет minSDK = 11, поэтому для совместимости с устройствами перед Lollipop я использую эту библиотеку https://github.com/ozodrukh/CircularReveal

У меня есть фрагмент с FloatingActionButton, который при касании преобразует себя в CardView, как описано здесь преобразований FAB.

Как только карта открыта, у нее есть кнопка, чтобы вернуть анимацию, преобразовав карту в FAB. Теперь моя проблема заключается в следующем: скажем, пользователь нажимает FAB, и открывается CardView. Теперь пользователь поворачивает свое устройство, поэтому активность сбрасывает фрагмент. Чего я хочу добиться, так это чтобы карта оставалась видимой и открытой, а FAB должен быть отключен и невидим. Проблема в том, что если я просто использую setVisibility(View.INVISIBLE) на моем FAB это не работает (обратите внимание, что если я использую getVisibility() сразу после установки его невидимым, он корректно возвращает мне значение 4 == View.INVISIBLE, но фаб все еще виден). Я должен обернуть setVisibility(...) позвонить внутрь postDelayed() с задержкой не менее 50-100 мс, чтобы сделать потрясающее изображение невидимым.

Итак, мой вопрос: я делаю все правильно или есть лучший способ выполнить то, что я хочу (потому что это кажется мне очень уродливым)?

Вот код Это мой XML-фрагмент:

<android.support.design.widget.CoordinatorLayout
    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="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/my_appbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/toolbar_expanded_height"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="70dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <android.support.v7.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/ToolbarPopupTheme"
                app:layout_collapseMode="pin"/>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
    ...
    <io.codetail.widget.RevealFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include layout="@layout/my_fragment" />
    </io.codetail.widget.RevealFrameLayout>
    <android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        app:fabSize="mini"
        app:layout_anchor="@+id/my_appbar"
        app:layout_anchorGravity="bottom|left|start" />
</android.support.design.widget.CoordinatorLayout>

Это макет XML включенного CardView:

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp"
    android:layout_gravity="center"
    card_view:cardCornerRadius="2dp"
    android:visibility="invisible"
    android:focusableInTouchMode="true">

    <RelativeLayout android:layout_width="match_parent"
        android:layout_height="match_parent">

        ...
        <LinearLayout android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="end">
            <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="Ok" />
            <Button android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Cancel" />
        </LinearLayout>
    </RelativeLayout>
</android.support.v7.widget.CardView>

И это код моего фрагмента:

public class MyFragment extends Fragment {

    private static final String CARD_OPEN_TAG = "CARD_OPEN_TAG";

    public static MyFragment newInstance(){
        return new MyFragment();
    }

    private int cardOpen;
    private FloatingActionButton fabAddPublication;
    private CardView card;
    private Button cardCancel;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        final View rootView = inflater.inflate(R.layout.fragment_magazines, container, false);
        toolbar = (Toolbar) rootView.findViewById(R.id.layout);

        ...

        // Initialize view status
        if (savedInstanceState != null){
            cardOpen = savedInstanceState.getInt(CARD_OPEN_TAG);
        } else {
            cardOpen = -1;
        }

        ...

        // Get FAB reference
        fab = (FloatingActionButton) rootView.findViewById(R.id.fab_id);
        // Get card reference
        card = (CardView) rootView.findViewById(R.id.card_id);
        editorPublication.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                // Using this event because I need my card to be measured to move correctly fab at his center
                if (cardOpen != -1){
                    // Move FAB to center of card
                    fab.setTranslationX(coordX); // WORKS
                    fab.setTranslationY(coordY); // WORKS
                    // fab.setVisibility(View.INVISIBLE) -> DOESN'T WORK, fab remain visible on top and at center of my card
                    // Ugly workaround
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            // Hide FAB
                            fab.setVisibility(View.INVISIBLE);
                        }
                    }, 50); // Sometimes fails: if device/emulator use too much time to "rotate" screen, fab stay visible
                    // Remove listener
                    ViewTreeObserver obs = card.getViewTreeObserver();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
                        obs.removeOnGlobalLayoutListener(this);
                    else obs.removeGlobalOnLayoutListener(this);
                }
            }
        });
        if (editorOpen != -1){
            fab.setEnabled(false); // WORKS
            card.setVisibility(View.VISIBLE); // WORKS
        }
        // Get editors buttons reference
        cardCancel = (Button) card.findViewById(R.id.card_cancel_id);
        // Set FAB listener
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Explode FAB
                explodeFab(fab, card); // This method trigger the reveal animation
                cardOpen = card.getId();
            }
        });
        // Set editors button listeners
        cardCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Implode FAB
                implodeFAB(fab, card); // This card reverts the reveal animation
        cardOpen = -1;
            }
        });

        ...

        return rootView;
    }

    @Override
    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        ...
        outState.putInt(CARD_OPEN_TAG, cardOpen);
    }

}

1 ответ

Я не думаю, что вы делаете правильно, и вот почему:

1.

Используемая вами библиотека циклического отображения несовместима с аппаратным ускорением в Android 11–17 (3,0–4,2). Он использует Canvas.clipPath() - метод, который был реализован в программном обеспечении только до Android 4.3. Это означает, что вам нужно отключить аппаратное ускорение, иначе ваше приложение будет зависать при неподдерживаемом вызове OpenGL.

Лучший способ обрезать макеты - использовать Canvas.saveLayer()/restoreLayer(). Это единственный способ поддержки всех устройств, получения сглаженного изображения и правильной поддержки аннулирования / разметки / отрисовки.

2.

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

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

Может быть, вы вызываете setVisibility(true) где-то в коде, и поэтому ваш FAB виден? Настройка видимости в порядке и должна работать без задержек вызовов. Просто сохраните видимость как состояние FAB и восстановите ее после изменения ориентации.

Если вы хотите расположить FAB в центре панели инструментов, оберните их оба в FrameLayout (wrap_content) и расположите FAB с layout_gravity="center". Это должно позволить вам удалить макет слушателя.

3.

support.CardView не работает и не должен использоваться вообще. Это выглядит и работает немного по-другому на Lollipop и на старых системах. Тень другая, отступы разные, отсечение контента не работает на устройствах, предшествующих Lollipop, и т. Д. Вот почему трудно получить согласованные, хорошие результаты на всех платформах.

Вы должны рассмотреть возможность использования простых макетов для этой цели.

4.

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

Я не говорю "нет" для вашего случая, но вы можете удалить трансформацию и использовать выпадающее меню, нижний лист, статическую панель инструментов или диалог для этой цели.

Другие вопросы по тегам