1

我正在開發一個項目,我希望根據材料設計使用循環顯示效果。項目擁有minSDK = 11,因此與前棒棒糖設備的兼容性,我使用這個庫https://github.com/ozodrukh/CircularReveal使用帶有棒棒糖循環顯示庫的setVisibility(View.INVISIBLE)

我已經與FloatingActionButton片段,輕敲後,將改變自己在CardView,喜歡這裏描述FAB transformations

一旦顯示卡片,它就會有一個按鈕來恢復動畫,將卡片重新轉換爲FAB。現在我的問題是這樣的:假設用戶點擊FAB並顯示CardView。現在用戶旋轉他的設備,所以活動重置片段。我想要實現的是卡片保持可見和透露狀態,而FAB應該被禁用且不可見。問題是,如果我簡單地在我的FAB上使用setVisibility(View.INVISIBLE)它不起作用(請注意,如果我在使用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> 

這是包括CardView的XML佈局:

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

} 

回答

0

我不要認爲你在做什麼是正確的,這是爲什麼:

1.

該通告顯示您正在使用的庫與Android 11至17(3.0至4.2)上的硬件加速不兼容。它使用了Canvas.clipPath() - 這是一種僅在Android 4.3以前的軟件中實現的方法。這意味着您必須關閉硬件加速功能,否則您的應用會在不支持的OpenGL通話中崩潰。

剪輯佈局的最佳方式是使用Canvas.saveLayer()/ restoreLayer()。這是支持所有設備,獲取抗鋸齒圖像並正確支持無效/佈局/繪製流程的唯一方法。

2.

依託定時器和佈局聽衆改變佈局意味着東西是不是真的爲你工作。每個更改都可以直接執行而無需等待。你只需要爲這段代碼找到合適的地方。

定時器還可以在您的應用程序處於後臺時觸發。這意味着它會在嘗試從Timer線程訪問UI時崩潰。

也許你在代碼的某個地方調用setVisibility(true),這就是爲什麼你的FAB是可見的?設置可見性是可以的,應該沒有任何延遲的調用。只需將可視性保存爲FAB的狀態並在方向更改後恢復。

如果您希望將FAB放置在工具欄的中心,請將它們都包裝在FrameLayout(wrap_content)中,並使用layout_gravity =「center」定位FAB。這應該允許您刪除佈局偵聽器。

3.

support.CardView壞了,不應該使用。它看起來和Lollipop和舊系統有點不同。陰影是不同的,填充不同的是,內容剪輯不會對預棒棒糖設備的工作,等等。這就是爲什麼它是很難獲得在所有平臺上一致的,效果不錯。

您應該考慮使用簡單的佈局用於這一目的。

4.

一些動畫是長得帥,但難以實現,不給任何價值,迅速成爲刺激性,因爲用戶必須等待動畫,他每次做完/她點擊按鈕。

我不是爲你的情況說不做,但你可以考慮刪除的改造和使用下拉菜單,底部片,靜態工具欄或爲目的的對話。

+0

Zielony您好,感謝您的時間。我開始認爲你對刪除這部動畫是正確的,尤其是因爲我不是圖形專家。我之所以使用這個庫,是因爲它宣稱在Lollipop之前的Android版本中啓用了這種效果,並且我沒有提到任何關於硬件加速問題的信息(或者我錯了嗎?)。 我正在使用CardView來顯示一個小表格來在我的數據庫中創建一個新條目(只有2個edittexts)。如果我決定更換CardView,那麼您爲此目的建議我做什麼? DialogFragment(我使用片段)? – MatteoBelfiori

+0

我談論硬件加速問題被報告爲這裏的問題:https://github.com/ozodrukh/CircularReveal/issues/27。我會在那裏用某種對話,但我不知道你的情況,這只是我的看法。選擇最適合你的方式。 – Zielony

+0

謝謝Zielony,我想我會去找一個DialogFragment。 – MatteoBelfiori