나는 아래와 같이 View
트랜지션을 추가하고 싶은 프로젝트에서 일하고 있습니다. 나는 어디에서 시작해야할지 모르겠다. 아무도 나를 도울 수 있니?android에서 이와 같은 뷰 전환을 디자인하는 방법
답변
당신이 효과의 유형을 달성 할 수있는 몇 가지 방법이 있습니다, 그 어휘 응용 프로그램이 처리하지만, 매우 유사한 효과를 얻을 수있는 아주 쉬운 방법입니다 방법을 모르고는 여러 RecyclerView.ViewHolder
유형을 사용하는 것입니다 없습니다 DefaultItemAnimator
애니메이션 작업을 처리하도록합시다. 우리의 모델은 우리의 RecyclerView.Adapter
ReclerView.ViewHolder
이 팽창 알리기 위해 type
뿐만 아니라 우리가 표시하고있는 데이터를 포함 할 것입니다
모델 : 여기 그것에 대해 이동하는 방법 중 하나입니다. 우리는 몇 가지 ExpandableModel
데이터를 바인딩하는 기본 ReclerView.ViewHolder
을 정의 할뿐만 아니라 좋은 OnClickListener
콜백을 우리에게 제공 할 수
@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
: 그래서,이 (AutoValue) 같이 보일 수 있습니다.
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
01,234,278,398,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_EXPANDED
또는 TYPE_COLLAPSED
ExpandableModel
and because DefaultItemAnimator
is already applied to RecyclerView
으로 전화를 걸면 RecyclerView.Adapter.notifyItemChanged
으로 전화하면 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;
}
}
더미 데이터
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)
당신은 생명의 은인입니다 ..... –
지금까지 해보신 것은 무엇입니까? –
방금 전에 처음 세 개의 사용자 정의보기를 만들었습니다 .... 제가 말했듯이 첫 번째 레이아웃에서 두 번째 레이아웃으로 어떻게 부드럽게 전환 할 수 있는지 전혀 모르겠습니다. –
잘보십시오 - https://github.com/wasabeef/awesome-android-ui – SanVed