Je travaille sur un projet dans lequel je souhaite utiliser l'effet Circular Reveal selon le Material Design. Projet a minSDK = 11, donc pour la compatibilité avec les appareils pré-Lollipop, j'utilise cette bibliothèque https://github.com/ozodrukh/CircularRevealUtilisation de setVisibility (View.INVISIBLE) avec la bibliothèque pre Lollipop Circular Reveal
J'ai un fragment avec un FloatingActionButton que, quand on tape dessus, va se transformer en Vignettes, comme décrit ici FAB transformations .
Une fois que la carte est révélée, elle dispose d'un bouton pour inverser l'animation, re-transformant la carte en FAB. Maintenant, mon problème est le suivant: disons qu'un utilisateur tape sur le FAB et que le CardView est révélé. Maintenant, l'utilisateur fait pivoter son appareil, l'activité réinitialise le fragment. Ce que je veux réaliser, c'est que la carte reste visible et visible, alors que le FAB doit être désactivé et invisible. Le problème est que si j'utilise simplement setVisibility(View.INVISIBLE)
sur mon FAB il ne fonctionne pas (notez que si j'utilise getVisibility()
dessus juste après l'avoir rendu invisible, il me renvoie correctement la valeur 4 == View.INVISIBLE, mais le fab est encore visible). Je dois envelopper l'appel setVisibility(...)
dans un postDelayed()
avec au moins 50-100 ms de retard pour rendre le fab invisible. Donc, ma question est la suivante: est-ce que je fais les choses correctement ou y at-il une meilleure façon d'accomplir ce que je veux (parce que cela me semble très moche)?
Voici du code. Ceci est ma mise en page XML du fragment:
<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>
Ceci est la mise en page XML du Vignettes inclus:
<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>
Et voici le code de mon Fragment:
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);
}
}
Salut Zielony, merci pour votre temps. Je commence à penser que vous avez raison de supprimer cette animation, surtout parce que je ne suis pas un expert en matière de graphisme. J'utilisais cette librairie car elle prétendait activer cet effet dans les versions Android antérieures à Lollipop et je n'ai rien lu sur les problèmes d'accélération matérielle (ou est-ce que je me trompe encore?). J'utilisais CardView pour montrer un petit formulaire pour créer une nouvelle entrée dans ma base de données (seulement 2 éditiés). Si je décide de remplacer CardView, que me suggérez-vous à cet effet? Un DialogFragment (j'utilise des fragments)? – MatteoBelfiori
Le problème d'accélération matérielle dont je parle a été signalé comme un problème ici: https://github.com/ozodrukh/CircularReveal/issues/27. J'utiliserais une sorte de dialogue là-bas, mais je ne connais pas votre cas et c'est seulement mon opinion. Choisissez ce qui fonctionne le mieux pour vous. – Zielony
Merci Zielony, je pense que je vais aller pour un DialogFragment. – MatteoBelfiori