我有一个recyclerview,在其中单击某个项目时,它会打开一个编辑对话框活动。我使用了一个MorphTransform转换(来自plaid),该转换扩展了ChangeBounds转换。该对话框应该从视座中来回变形,但是相反,我得到了一些不同的行为:
1。每当对话框位于查看器项的顶部时,它都会变回该项目,但是当对话框位于查看器项的上方或下方时,它将在查看器上方“翻转”,而不是从查看器扩展。
2.当对话框“变形”回到视图支架时,它会在短时间内被“卡住”,并且无法平滑地变形为视图支架。我尝试使用颜色动画制作器的持续时间(ObjectAnimator.ofArgb),但未提供所需的结果。
Here is a gif for current behaviour
这是我使用的过渡类:
public class MorphTransform extends ChangeBounds {
private static final String EXTRA_SHARED_ELEMENT_START_COLOR =
"EXTRA_SHARED_ELEMENT_START_COLOR";
private static final String EXTRA_SHARED_ELEMENT_START_CORNER_RADIUS =
"EXTRA_SHARED_ELEMENT_START_CORNER_RADIUS";
private static final long DEFAULT_DURATION = 300L;
private final int startColor;
private final int endColor;
private final int startCornerRadius;
private final int endCornerRadius;
public MorphTransform(@ColorInt int startColor, @ColorInt int endColor,
int startCornerRadius, int endCornerRadius) {
this.startColor = startColor;
this.endColor = endColor;
this.startCornerRadius = startCornerRadius;
this.endCornerRadius = endCornerRadius;
setDuration(DEFAULT_DURATION);
setPathMotion(new GravityArcMotion());
}
/**
* Configure {@code intent} with the extras needed to initialize this transition.
*/
public static void addExtras(@NonNull Intent intent,
@ColorInt int startColor,
int startCornerRadius) {
intent.putExtra(EXTRA_SHARED_ELEMENT_START_COLOR, startColor);
intent.putExtra(EXTRA_SHARED_ELEMENT_START_CORNER_RADIUS, startCornerRadius);
}
/**
* Configure {@link MorphTransform}s & set as {@code activity}'s shared element enter and return
* transitions.
*/
public static void setup(@NonNull Activity activity,
@Nullable View target,
@ColorInt int endColor,
int endCornerRadius) {
final Intent intent = activity.getIntent();
if (intent == null
|| !intent.hasExtra(EXTRA_SHARED_ELEMENT_START_COLOR)
|| !intent.hasExtra(EXTRA_SHARED_ELEMENT_START_CORNER_RADIUS)) return;
final int startColor = activity.getIntent().
getIntExtra(EXTRA_SHARED_ELEMENT_START_COLOR, Color.TRANSPARENT);
final int startCornerRadius =
intent.getIntExtra(EXTRA_SHARED_ELEMENT_START_CORNER_RADIUS, 0);
final MorphTransform sharedEnter =
new MorphTransform(startColor, endColor, startCornerRadius, endCornerRadius);
// Reverse the start/end params for the return transition
final MorphTransform sharedReturn =
new MorphTransform(endColor, startColor, endCornerRadius, startCornerRadius);
if (target != null) {
sharedEnter.addTarget(target);
sharedReturn.addTarget(target);
}
activity.getWindow().setSharedElementEnterTransition(sharedEnter);
activity.getWindow().setSharedElementReturnTransition(sharedReturn);
}
@Override
public Animator createAnimator(final ViewGroup sceneRoot,
final TransitionValues startValues,
final TransitionValues endValues) {
final Animator changeBounds = super.createAnimator(sceneRoot, startValues, endValues);
if (changeBounds == null) return null;
TimeInterpolator interpolator = getInterpolator();
if (interpolator == null) {
interpolator = AnimUtils.getFastOutSlowInInterpolator(sceneRoot.getContext());
}
final MorphDrawable background = new MorphDrawable(startColor, startCornerRadius);
endValues.view.setBackground(background);
final Animator color = ObjectAnimator.ofArgb(background, MorphDrawable.COLOR, endColor);
final Animator corners =
ObjectAnimator.ofFloat(background, MorphDrawable.CORNER_RADIUS, endCornerRadius);
// ease in the dialog's child views (fade in & staggered slide up)
if (endValues.view instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) endValues.view;
final long duration = getDuration();
float offset = vg.getHeight() / 3;
for (int i = 0; i < vg.getChildCount(); i++) {
View v = vg.getChildAt(i);
// v.setTranslationY(offset);
v.setAlpha(0f);
v.animate()
// .alpha(0.5f)
// .translationY(0f)
.setDuration(duration)
.alpha(1f)
.setStartDelay(duration)
.setInterpolator(interpolator);
// offset *= 1.8f;
}
}
color.setInterpolator(AnimUtils.getFastOutSlowInInterpolator(sceneRoot.getContext()));
final AnimatorSet transition = new AnimatorSet();
transition.playTogether(changeBounds, corners, color);
transition.setDuration(getDuration());
transition.setInterpolator(interpolator);
return transition;
}
在这里我称之为对话活动:
ProfileFragment:
@SuppressLint("RestrictedApi") //for startActivityForResult()
private void showEditStatDialog(int position, List<MultipleEntity> items, ViewGroup statViewHolder, int dialogType) {
statViewHolder.setTransitionName(getResources().getString(R.string.profile_transition_stat_to_dialog));
String itemTitle = ((Stat)items.get(position).getContent()).getTitle();
String currentValue = ((Stat) items.get(position).getContent()).getValue();
Intent dialogIntent = BaseDialogActivity.createIntentForEditTextDialog(getContext(), dialogType, itemTitle, currentValue, getString(R.string.dialog_stat_button_insert), position);
dialogIntent.putExtra(TRANSITION_NAME_EXTRA, ViewCompat.getTransitionName(statViewHolder));
MorphTransform.addExtras(dialogIntent, ContextCompat.getColor(getContext(), R.color.bright_blue), 5);
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(getActivity(), statViewHolder, ViewCompat.getTransitionName(statViewHolder));
getActivity().startActivityForResult(dialogIntent, DIALOG_RC, options.toBundle());
这是来自recyclerview适配器的viewHolder类:
public static class StatViewHolder extends RecyclerView.ViewHolder {
View colorView;
TextView titleTv;
TextView valueTv;
TextView additionalValueInfoTv;
public StatViewHolder(final View itemView) {
super(itemView);
colorView = itemView.findViewById(R.id.fragment_profile_list_item_color_view);
titleTv = itemView.findViewById(R.id.fragment_profile_list_item_title);
valueTv = itemView.findViewById(R.id.fragment_profile_list_item_value);
additionalValueInfoTv = itemView.findViewById(R.id.fragment_profile_list_item_additional_value_info);
}
public static void bind(final int position, final StatViewHolder holder) {
holder.colorView.setBackgroundColor(((Stat) items.get(position).getContent()).getColorRes());
holder.titleTv.setText(((Stat) items.get(position).getContent()).getTitle());
holder.valueTv.setText(((Stat) items.get(position).getContent()).getValue());
holder.additionalValueInfoTv.setText(((Stat) items.get(position).getContent()).getAdditionalValueInfo());
ViewCompat.setTransitionName(holder.itemView, ((Stat)items.get(position).content).getTitle() + position);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onStatClicked(holder.getAdapterPosition(), holder.itemView);
}
});
}
这是Dialog活动类的摘录:
public static Intent createIntentForEditTextDialog(Context context, @NonNull int dialogType, @NonNull String title, @Nullable String hint, @Nullable String buttonText, @Nullable int position) {
Bundle extra = new Bundle();
extra.putInt(DIALOG_TYPE_EXTRA, dialogType);
extra.putString(EDITTEXT_HINT_EXTRA, hint);
extra.putString(BUTTON1_TEXT_EXTRA, buttonText);
extra.putString(TITLE_TEXT_EXTRA, title);
extra.putInt(SELECTED_STAT_POSITION, position);
Intent intent = new Intent(context, BaseDialogActivity.class);
intent.putExtra(DIALOG_EXTRAS_BUNDLE, extra);
return intent;
}
/*...add more intents for other types of dialogs...*/
@Override
public void onBackPressed() {
super.onBackPressed();
supportFinishAfterTransition();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTransitionName = getIntent().getStringExtra(ProfileFragment.TRANSITION_NAME_EXTRA);
initViews();
ViewGroup container = findViewById(R.id.dialog_container);
container.setTransitionName(mTransitionName);
// this.setFinishOnTouchOutside(true);
MorphTransform.setup(this, findViewById(R.id.dialog_container), getResources().getColor(R.color.white), 8);
}
这是我在对话框活动中使用的主题:
<!--DialogStyle-->
<style name="DialogStyle" parent="@style/Theme.AppCompat.Dialog">
<item name="android:windowFrame">@null</item>
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentTransitions">true</item>
<item name="android:windowSharedElementsUseOverlay">false</item>
</style>
这是对话框活动布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:id="@+id/dialog_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="@dimen/dialog_padding_horizontal"
android:paddingVertical="@dimen/dialog_padding"
android:background="@color/trans_white_stat"
tools:context=".ui.mainscreen.MainScreenActivity">
<TextView
android:id="@+id/dialog_title_tv"
style="@style/DialogTitle"
android:text="Ooops!"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/dialog_edittext"
style="@style/DialogEditText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/dialog_title_tv" />
<Button
android:id="@+id/dialog_button"
style="@style/DialogButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/dialog_edittext" />
</android.support.constraint.ConstraintLayout>