1

中设计这样的视图转换我正在创建一个项目,我想添加一个如下所示的View转换。我不知道从哪里开始,有人可以帮我吗?如何在android

+0

到目前为止您尝试过了什么? –

+0

我刚刚创建了最初的三个自定义视图....正如我所说的,我不知道如何从第一个布局转换到具有平滑视图转换的第二个布局。 –

+0

试试这些以及 - https://github.com/wasabeef/awesome-android-ui – SanVed

回答

1

有几种方法,你可以实现这种类型的效果,没想到的词汇应用程序是如何处理它,而是一个非常简单的方法来得到一个非常类似的效果是使用多个RecyclerView.ViewHolder类型,然后让DefaultItemAnimator负责动画工作。这里是去了解的一个方法:

型号

我们的模型也会包含我们显示的数据以及一个type通知我们RecyclerView.AdapterReclerView.ViewHolder膨胀。因此,它可能是这个样子(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

我们可以定义将结合一些ExpandableModel数据基本ReclerView.ViewHolder以及为我们提供了一个很好的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())); 
    } 

} 

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布局

<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> 

适配器

现在,我们可以创建RecyclerView.Adapter。基本上,无论何时点击某个项目,我们将用TYPE_EXPANDEDTYPE_COLLAPSEDExpandableModeland because DefaultItemAnimator is already applied to RecyclerView替换它,在这两种类型的RecyclerView.ViewHolder之间调用RecyclerView.Adapter.notifyItemChanged会很好。

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

} 

伪数据

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

额外

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

} 

结果(video

+1

你是一个救星..... –