更改viewHolder“翻转”视图而不是使其变形的边界过渡

时间:2018-08-13 13:48:48

标签: android android-animation android-transitions

我有一个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>
  1. 如何使对话框平滑地变回查看器项?
  2. 如何在所有情况下都使视图保持器扩展到对话框中,而不是有时切换到该对话框中?
    谢谢。

0 个答案:

没有答案