1

Je travaille sur un projet où je veux ajouter une transition View comme ci-dessous. Je n'ai aucune idée par où commencer, quelqu'un peut-il m'aider?Comment concevoir une transition de vue comme ça dans android

+0

Qu'est-ce que vous avez essayé jusqu'à présent? –

+0

Je viens de créer les trois premières vues personnalisées .... comme je l'ai dit, je n'ai aucune idée de comment puis-je passer de la première mise en page à la deuxième mise en page avec cette transition de vue lisse. –

+0

Essayez aussi ces - https://github.com/wasabeef/awesome-android-ui – SanVed

Répondre

1

Il y a plusieurs façons dont vous pouvez réaliser ce type d'effet, aucune idée de comment cette application de vocabulaire est la manipulation, mais un joli moyen facile d'obtenir un effet similaire est d'utiliser plusieurs types RecyclerView.ViewHolder puis laissez DefaultItemAnimator prendre soin du travail d'animation. Voici une façon d'aller à ce sujet:

Modèle

Notre modèle va contenir les données que nous sommes d'affichage ainsi qu'un type pour informer notre RecyclerView.Adapter qui ReclerView.ViewHolder à gonfler. Ainsi, il pourrait ressembler à ceci (AutoValue):

@AutoValue 
public abstract class ExpandableModel { 

    public static final int TYPE_STATIC = 0; 
    public static final int TYPE_EXPANDED = 1; 
    public static final int TYPE_COLLAPSED = 2; 

    @Nullable public abstract List<ExpandableModel> data(); 
    public abstract String title(); 
    public abstract int progress(); 
    public abstract int max(); 
    public abstract int type(); 

    public static ExpandableModel createExpanded(List<ExpandableModel> data, 
               String title, int progress, int max) { 
     return new AutoValue_ExpandableModel(data, title, progress, max, TYPE_EXPANDED); 
    } 

    public static ExpandableModel createCollapsed(List<ExpandableModel> data, 
                String title, int progress, int max) { 
     return new AutoValue_ExpandableModel(data, title, progress, max, TYPE_COLLAPSED); 
    } 

    public static ExpandableModel createExpanded(ExpandableModel model) { 
     return new AutoValue_ExpandableModel(
       model.data(), model.title(), model.progress(), model.max(), TYPE_EXPANDED); 
    } 

    public static ExpandableModel createCollapsed(ExpandableModel model) { 
     return new AutoValue_ExpandableModel(
       model.data(), model.title(), model.progress(), model.max(), TYPE_COLLAPSED); 
    } 

    public static ExpandableModel createStatic(String title, int progress, int max) { 
     return new AutoValue_ExpandableModel(null, title, progress, max, TYPE_STATIC); 
    } 

} 

ViewHolder

Nous pouvons définir une ReclerView.ViewHolder de base qui lie certains ExpandableModel données ainsi que nous fournir une belle rappel OnClickListener.

public abstract class ExpandableViewHolder extends RecyclerView.ViewHolder { 

    public ExpandableViewHolder(ViewGroup parent, int layout) { 
     super(LayoutInflater.from(parent.getContext()).inflate(layout, parent, false)); 
    } 

    public void setItemClickListener(OnItemClickListener clickListener) { 
     itemView.setOnClickListener(v -> { 
      final int adapterPosition = getAdapterPosition(); 
      if (adapterPosition != RecyclerView.NO_POSITION) { 
       clickListener.onItemClick(itemView, adapterPosition); 
      } 
     }); 
    } 

    public abstract void bind(ExpandableModel model); 

    public interface OnItemClickListener { 
     void onItemClick(View itemView, int position); 
    } 

} 

ExpandedViewHolder

public class ExpandedViewHolder extends ExpandableViewHolder { 

    private final TextView title; 
    private final TextView completion; 
    private final ProgressBar progress; 
    private final RecyclerView recycler; 

    public ExpandedViewHolder(ViewGroup parent) { 
     super(parent, R.layout.adapter_view_expanded); 
     title = itemView.findViewById(R.id.expanded_category); 
     completion = itemView.findViewById(R.id.expanded_completion); 
     progress = itemView.findViewById(R.id.expanded_progress); 
     recycler = itemView.findViewById(R.id.expanded_recycler); 
     recycler.addItemDecoration(new SpaceItemDecoration(10)); 
    } 

    @Override 
    public void bind(ExpandableModel model) { 
     title.setText(model.title()); 
     completion.setText(model.progress() + "/" + model.max()); 
     progress.setMax(model.max()); 
     progress.setProgress(model.progress()); 
     recycler.setAdapter(new ExpandableAdapter(model.data())); 
    } 

} 

mise en page de ExpandedViewHolder

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="350dp" 
    android:background="#ffFFC857" 
    android:orientation="vertical"> 

    <TextView 
     android:id="@+id/expanded_category" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginTop="16dp" 
     android:gravity="center" 
     android:textColor="#ffffffff" 
     android:textIsSelectable="false" 
     android:textSize="28sp" 
     tools:text="Basic Words" /> 

    <TextView 
     android:id="@+id/expanded_completion" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginTop="8dp" 
     android:gravity="center" 
     android:textColor="#ffffffff" 
     android:textIsSelectable="false" 
     android:textSize="18sp" 
     tools:text="174/174 mastered" /> 

    <ProgressBar 
     android:id="@+id/expanded_progress" 
     style="@style/Widget.AppCompat.ProgressBar.Horizontal" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginEnd="16dp" 
     android:layout_marginStart="16dp" 
     android:layout_marginTop="16dp" 
     tools:progress="100" /> 

    <android.support.v4.widget.Space 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1" /> 

    <android.support.v7.widget.RecyclerView 
     android:id="@+id/expanded_recycler" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_gravity="bottom" 
     android:layout_marginBottom="4dp" 
     android:orientation="horizontal" 
     app:layoutManager="android.support.v7.widget.LinearLayoutManager" /> 

</LinearLayout> 

CollapsedViewHolder

public class CollapsedViewHolder extends ExpandableViewHolder { 

    private final TextView title; 
    private final TextView completion; 
    private final ProgressBar progress; 

    public CollapsedViewHolder(ViewGroup parent) { 
     super(parent, R.layout.adapter_view_collapsed); 
     title = itemView.findViewById(R.id.collapsed_category); 
     completion = itemView.findViewById(R.id.collapsed_completion); 
     progress = itemView.findViewById(R.id.collapsed_progress); 
    } 

    @Override 
    public void bind(ExpandableModel model) { 
     title.setText(model.title()); 
     completion.setText(model.progress() + "/" + model.max()); 
     progress.setMax(model.max()); 
     progress.setProgress(model.progress()); 
    } 

} 

CollapsedViewHolder mise en page

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="165dp" 
    android:layout_margin="4dp" 
    android:background="#ffffffff" 
    android:orientation="vertical"> 

    <TextView 
     android:id="@+id/collapsed_category" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginTop="16dp" 
     android:gravity="center" 
     android:textColor="#ff066FA5" 
     android:textIsSelectable="false" 
     android:textSize="28sp" 
     tools:text="Basic Words" /> 

    <TextView 
     android:id="@+id/collapsed_completion" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginTop="8dp" 
     android:gravity="center" 
     android:textColor="#ffAEB8C3" 
     android:textIsSelectable="false" 
     android:textSize="18sp" 
     tools:text="174/174 mastered" /> 

    <ProgressBar 
     android:id="@+id/collapsed_progress" 
     style="@style/Widget.AppCompat.ProgressBar.Horizontal" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginEnd="16dp" 
     android:layout_marginStart="16dp" 
     android:layout_marginTop="16dp" 
     tools:progress="100" /> 

</LinearLayout> 

Adaptateur

Maintenant, nous pouvons créer notre RecyclerView.Adapter. Fondamentalement, chaque fois qu'un élément est cliqué, nous allons le remplacer par un TYPE_EXPANDED ou TYPE_COLLAPSEDExpandableModeland because DefaultItemAnimator is already applied to RecyclerView, appelant RecyclerView.Adapter.notifyItemChanged va bien animer entre les deux types de RecyclerView.ViewHolder.

public class ExpandableAdapter extends RecyclerView.Adapter<ExpandableViewHolder> { 

    private final List<ExpandableModel> data = new ArrayList<>(0); 

    private int expandedPosition; 

    public ExpandableAdapter(Collection<ExpandableModel> data) { 
     this.data.addAll(data); 
    } 

    @Override 
    public ExpandableViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     switch (viewType) { 
      case TYPE_EXPANDED: 
       final ExpandedViewHolder expandedHolder = new ExpandedViewHolder(parent); 
       expandedHolder.setItemClickListener((itemView, position) -> collapse(position)); 
       return expandedHolder; 
      case TYPE_COLLAPSED: 
       final CollapsedViewHolder collapsedHolder = new CollapsedViewHolder(parent); 
       collapsedHolder.setItemClickListener((itemView, position) -> { 
        collapseCurrent(); 
        expand(position); 
       }); 
       return collapsedHolder; 
      case TYPE_STATIC: 
       final CollapsedViewHolder staticHolder = new CollapsedViewHolder(parent); 
       staticHolder.setItemClickListener((itemView, position) -> { 
        final ExpandableModel model = data.get(position); 
        Snackbar.make(itemView, model.title(), Snackbar.LENGTH_SHORT).show(); 
       }); 
       return staticHolder; 
      default: 
       throw new IllegalArgumentException("unknown type"); 
     } 
    } 

    @Override 
    public void onBindViewHolder(ExpandableViewHolder holder, int position) { 
     holder.bind(data.get(holder.getAdapterPosition())); 
    } 

    @Override 
    public int getItemCount() { 
     return data.size(); 
    } 

    @Override 
    public int getItemViewType(int position) { 
     return data.get(position).type(); 
    } 

    private void collapseCurrent() { 
     final ExpandableModel curr = data.get(expandedPosition); 
     data.set(expandedPosition, ExpandableModel.createCollapsed(curr)); 
     notifyItemChanged(expandedPosition); 
    } 

    private void collapse(int position) { 
     final ExpandableModel curr = data.get(position); 
     data.set(position, ExpandableModel.createCollapsed(curr)); 
     notifyItemChanged(position); 
    } 

    private void expand(int position) { 
     final ExpandableModel curr = data.get(position); 
     data.set(position, ExpandableModel.createExpanded(curr)); 
     notifyItemChanged(position); 
     expandedPosition = position; 
    } 

} 

données fictives

final Random ran = new SecureRandom(); 

    final List<ExpandableModel> basic = new ArrayList<>(0); 
    for (int i = 0; i < 10; i++) { 
     final int max = 10; 
     final int progress = ran.nextInt(max + 1); 
     final String title = ("Basic Words: " + (i + 1)); 
     basic.add(ExpandableModel.createStatic(title, progress, max)); 
    } 

    final List<ExpandableModel> intermediate = new ArrayList<>(0); 
    for (int i = 0; i < 10; i++) { 
     final int max = 10; 
     final int progress = ran.nextInt(max + 1); 
     final String title = ("Intermediate Words: " + (i + 1)); 
     intermediate.add(ExpandableModel.createStatic(title, progress, max)); 
    } 

    final List<ExpandableModel> advanced = new ArrayList<>(0); 
    for (int i = 0; i < 10; i++) { 
     final int max = 10; 
     final int progress = ran.nextInt(max + 1); 
     final String title = ("Advanced Words: " + (i + 1)); 
     advanced.add(ExpandableModel.createStatic(title, progress, max)); 
    } 

    final List<ExpandableModel> data = new ArrayList<>(0); 
    data.add(ExpandableModel.createCollapsed(basic, "Basic Words", 7, 10)); 
    data.add(ExpandableModel.createCollapsed(intermediate, "Intermediate Words", 5, 10)); 
    data.add(ExpandableModel.createCollapsed(advanced, "Advanced Words", 3, 10)); 

    final RecyclerView recycler = findViewById(android.R.id.list); 
    recycler.setAdapter(new ExpandableAdapter(data)); 

supplémentaires

public class SpaceItemDecoration extends RecyclerView.ItemDecoration { 

    private final int space; 

    public SpaceItemDecoration(int space) { 
     this.space = space; 
    } 

    @Override 
    public void getItemOffsets(Rect outRect, View view, 
           RecyclerView parent, RecyclerView.State state) { 
     final int childPosition = parent.getChildLayoutPosition(view); 
     if (childPosition == RecyclerView.NO_POSITION) { 
      return; 
     } 
     if (childPosition < 1 || childPosition >= 1) { 
      outRect.left = space; 
     } 
     if (childPosition == getTotalItemCount(parent) - 1) { 
      outRect.right = space; 
     } 
    } 

    private static int getTotalItemCount(RecyclerView parent) { 
     return parent.getAdapter().getItemCount(); 
    } 

} 

Résultats (video)

+1

vous êtes un épargnant de vie ..... –