Separate ExpandableViewHolder

This commit is contained in:
topjohnwu 2019-01-28 14:51:29 -05:00
parent 18ab6b51fd
commit 976c299657
5 changed files with 113 additions and 142 deletions

View File

@ -15,7 +15,7 @@ import com.topjohnwu.core.container.Policy;
import com.topjohnwu.core.database.MagiskDB;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.components.CustomAlertDialog;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.components.ExpandableViewHolder;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.FingerprintHelper;
@ -51,13 +51,13 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
public void onBindViewHolder(ViewHolder holder, int position) {
Policy policy = policyList.get(position);
holder.setExpanded(expandList[position]);
holder.settings.setExpanded(expandList[position]);
holder.trigger.setOnClickListener(view -> {
if (holder.isExpanded()) {
holder.collapse();
if (holder.settings.isExpanded()) {
holder.settings.collapse();
expandList[position] = false;
} else {
holder.expand();
holder.settings.expand();
expandList[position] = true;
}
});
@ -136,7 +136,7 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
return policyList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.app_name) TextView appName;
@BindView(R.id.package_name) TextView packageName;
@ -150,24 +150,32 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
@BindView(R.id.delete) ImageView delete;
@BindView(R.id.more_info) ImageView moreInfo;
private Container container = new Container();
ExpandableViewHolder settings;
public ViewHolder(View itemView) {
super(itemView);
new PolicyAdapter$ViewHolder_ViewBinding(this, itemView);
container.expandLayout = expandLayout;
setupExpandable();
}
settings = new ExpandableViewHolder(expandLayout) {
@Override
public void setExpanded(boolean expanded) {
super.setExpanded(expanded);
arrow.setRotation(expanded ? 180 : 0);
}
@Override
public Container getContainer() {
return container;
}
@Override
public void expand() {
super.expand();
setRotate(new RotateAnimation(0, 180,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f));
}
@Override
public void setExpanded(boolean expanded) {
ExpandableView.super.setExpanded(expanded);
arrow.setRotation(expanded ? 180 : 0);
@Override
public void collapse() {
super.collapse();
setRotate(new RotateAnimation(180, 0,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f));
}
};
}
private void setRotate(RotateAnimation rotate) {
@ -175,19 +183,5 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
rotate.setFillAfter(true);
arrow.startAnimation(rotate);
}
@Override
public void expand() {
ExpandableView.super.expand();
setRotate(new RotateAnimation(0, 180,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f));
}
@Override
public void collapse() {
ExpandableView.super.collapse();
setRotate(new RotateAnimation(180, 0,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f));
}
}
}

View File

@ -12,7 +12,7 @@ import android.widget.TextView;
import com.topjohnwu.core.container.SuLogEntry;
import com.topjohnwu.core.database.MagiskDB;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.components.ExpandableViewHolder;
import java.util.Collections;
import java.util.HashSet;
@ -84,13 +84,13 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
public void onBindItemViewHolder(LogViewHolder holder, int section, int position) {
SuLogEntry entry = logEntries.get(section).get(position);
int realIdx = getItemPosition(section, position);
holder.setExpanded(itemExpanded.contains(realIdx));
holder.expandable.setExpanded(itemExpanded.contains(realIdx));
holder.itemView.setOnClickListener(view -> {
if (holder.isExpanded()) {
holder.collapse();
if (holder.expandable.isExpanded()) {
holder.expandable.collapse();
itemExpanded.remove(realIdx);
} else {
holder.expand();
holder.expandable.expand();
itemExpanded.add(realIdx);
}
});
@ -122,7 +122,7 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
}
}
static class LogViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
static class LogViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.app_name) TextView appName;
@BindView(R.id.action) TextView action;
@ -132,18 +132,12 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
@BindView(R.id.cmd) TextView command;
@BindView(R.id.expand_layout) ViewGroup expandLayout;
private Container container = new Container();
ExpandableViewHolder expandable;
LogViewHolder(View itemView) {
super(itemView);
new SuLogAdapter$LogViewHolder_ViewBinding(this, itemView);
container.expandLayout = expandLayout;
setupExpandable();
}
@Override
public Container getContainer() {
return container;
expandable = new ExpandableViewHolder(expandLayout);
}
}
}

View File

@ -1,83 +0,0 @@
package com.topjohnwu.magisk.components;
import android.animation.ValueAnimator;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
public interface ExpandableView {
class Container {
public ViewGroup expandLayout;
ValueAnimator expandAnimator, collapseAnimator;
boolean mExpanded = false;
int expandHeight = 0;
}
// Provide state info
Container getContainer();
default void setupExpandable() {
Container container = getContainer();
setExpanded(false);
container.expandLayout.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (container.expandHeight == 0) {
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
container.expandLayout.measure(widthSpec, heightSpec);
container.expandHeight = container.expandLayout.getMeasuredHeight();
}
container.expandLayout.getViewTreeObserver().removeOnPreDrawListener(this);
container.expandAnimator = slideAnimator(0, container.expandHeight);
container.collapseAnimator = slideAnimator(container.expandHeight, 0);
return true;
}
});
}
default boolean isExpanded() {
return getContainer().mExpanded;
}
default void setExpanded(boolean expanded) {
Container container = getContainer();
container.mExpanded = expanded;
ViewGroup.LayoutParams layoutParams = container.expandLayout.getLayoutParams();
layoutParams.height = expanded ? container.expandHeight : 0;
container.expandLayout.setLayoutParams(layoutParams);
}
default void expand() {
Container container = getContainer();
if (container.mExpanded) return;
container.expandLayout.setVisibility(View.VISIBLE);
container.expandAnimator.start();
container.mExpanded = true;
}
default void collapse() {
Container container = getContainer();
if (!container.mExpanded) return;
container.collapseAnimator.start();
container.mExpanded = false;
}
default ValueAnimator slideAnimator(int start, int end) {
Container container = getContainer();
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(valueAnimator -> {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = container.expandLayout.getLayoutParams();
layoutParams.height = value;
container.expandLayout.setLayoutParams(layoutParams);
});
return animator;
}
}

View File

@ -0,0 +1,72 @@
package com.topjohnwu.magisk.components;
import android.animation.ValueAnimator;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
public class ExpandableViewHolder {
private ViewGroup expandLayout;
private ValueAnimator expandAnimator, collapseAnimator;
private boolean mExpanded = false;
private int expandHeight = 0;
public ExpandableViewHolder(ViewGroup viewGroup) {
expandLayout = viewGroup;
setExpanded(false);
expandLayout.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (expandHeight == 0) {
expandLayout.measure(0, 0);
expandHeight = expandLayout.getMeasuredHeight();
}
expandLayout.getViewTreeObserver().removeOnPreDrawListener(this);
expandAnimator = slideAnimator(0, expandHeight);
collapseAnimator = slideAnimator(expandHeight, 0);
return true;
}
});
}
public boolean isExpanded() {
return mExpanded;
}
public void setExpanded(boolean expanded) {
mExpanded = expanded;
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
layoutParams.height = expanded ? expandHeight : 0;
expandLayout.setLayoutParams(layoutParams);
}
public void expand() {
if (mExpanded) return;
expandLayout.setVisibility(View.VISIBLE);
expandAnimator.start();
mExpanded = true;
}
public void collapse() {
if (!mExpanded) return;
collapseAnimator.start();
mExpanded = false;
}
private ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(valueAnimator -> {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
layoutParams.height = value;
expandLayout.setLayoutParams(layoutParams);
});
return animator;
}
}

View File

@ -24,7 +24,7 @@ import com.topjohnwu.magisk.components.BaseActivity;
import com.topjohnwu.magisk.components.BaseFragment;
import com.topjohnwu.magisk.components.CustomAlertDialog;
import com.topjohnwu.magisk.components.EnvFixDialog;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.components.ExpandableViewHolder;
import com.topjohnwu.magisk.components.MagiskInstallDialog;
import com.topjohnwu.magisk.components.ManagerInstallDialog;
import com.topjohnwu.magisk.components.UninstallDialog;
@ -50,9 +50,8 @@ import butterknife.BindView;
import butterknife.OnClick;
public class MagiskFragment extends BaseFragment
implements SwipeRefreshLayout.OnRefreshListener, ExpandableView, Topic.Subscriber {
implements SwipeRefreshLayout.OnRefreshListener, Topic.Subscriber {
private Container expandableContainer = new Container();
private static boolean shownDialog = false;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
@ -83,6 +82,7 @@ public class MagiskFragment extends BaseFragment
private UpdateCardHolder magisk;
private UpdateCardHolder manager;
private ExpandableViewHolder snExpandableHolder;
private Transition transition;
@OnClick(R.id.safetyNet_title)
@ -92,7 +92,7 @@ public class MagiskFragment extends BaseFragment
safetyNetRefreshIcon.setVisibility(View.GONE);
safetyNetStatusText.setText(R.string.checking_safetyNet_status);
SafetyNet.check(requireActivity());
collapse();
snExpandableHolder.collapse();
};
if (!SafetyNet.EXT_APK.exists()) {
// Show dialog
@ -134,8 +134,7 @@ public class MagiskFragment extends BaseFragment
unbinder = new MagiskFragment_ViewBinding(this, v);
requireActivity().setTitle(R.string.magisk);
expandableContainer.expandLayout = expandLayout;
setupExpandable();
snExpandableHolder = new ExpandableViewHolder(expandLayout);
magisk = new UpdateCardHolder(inflater, root);
manager = new UpdateCardHolder(inflater, root);
@ -168,7 +167,7 @@ public class MagiskFragment extends BaseFragment
@Override
public void onRefresh() {
safetyNetStatusText.setText(R.string.safetyNet_check_text);
setExpanded(false);
snExpandableHolder.setExpanded(false);
mSwipeRefreshLayout.setRefreshing(false);
TransitionManager.beginDelayedTransition(root, transition);
@ -207,11 +206,6 @@ public class MagiskFragment extends BaseFragment
}
}
@Override
public Container getContainer() {
return expandableContainer;
}
private boolean hasGms() {
PackageManager pm = app.getPackageManager();
PackageInfo info;
@ -352,7 +346,7 @@ public class MagiskFragment extends BaseFragment
basicStatusIcon.setImageResource(b ? R.drawable.ic_check_circle : R.drawable.ic_cancel);
basicStatusIcon.setColorFilter(b ? colorOK : colorBad);
expand();
snExpandableHolder.expand();
} else {
@StringRes int resid;
switch (response) {