web-dev-qa-db-ja.com

ボトムシートのレイアウト変更をアニメーション化する

私のアプリケーションでは、うまく機能するボトムシート(サポートライブラリから)を使用しています。次に、シートが上にドラッグされている間にレイアウトの変更をアニメートしたいと思います。このためにBottomSheetCallbackのサブクラスを作成しました(これは通常Fragmentの内部クラスなので、このcalssで使用されるすべてのオブジェクトがここで初期化されるわけではありません)。

public class MyBehavior extends BottomSheetBehavior.BottomSheetCallback {

    Transition transition;
    float lastOffset = 0;
    Scene scene;

    public PlayerBehavior() {
        TransitionInflater inflater = TransitionInflater.from(getContext());
        transition = inflater.inflateTransition(R.transition.player);
        //transition.setDuration(300);

        scene = fullLayout;

        transition.setInterpolator(new Interpolator() {
            @Override
            public float getInterpolation(float v) {
                return lastOffset;
            }
        });
    }

    @Override
    public void onStateChanged(@NonNull View bottomSheet, int newState) {
        if(newState == BottomSheetBehavior.STATE_DRAGGING) {
            TransitionManager.go(scene, transition);
        }
    }

    @Override
    public void onSlide(View bottomSheet, final float slideOffset) {
        scene = (slideOffset > lastOffset) ? smallLayout : fullLayout;
        lastOffset = slideOffset;
    }
}

ご覧のとおり、異なるレイアウトファイルから2つのSceneと、Transitionを使用してシーン間をアニメーション化するカスタムTransitionManagerも作成しました。私の問題は、TransitionslideOffsetパラメーター(0-1の範囲)に基づいている必要があるが、TransitionManagerAnimationクラスを使用することです通常はAndroidの時間ベースの背景。

カスタムIntapolatorを作成しようとしましたが、これは正しく機能しません。では、時間ではなく外部変数に基づくTransitionを作成するにはどうすればよいですか?

27
Cilenco

あなたの説明に基づいて、Googleマップのボトムシートの動作のようなものを達成しようとしていると思います。 bottomsheetが上にドラッグされると、レイアウトが変更されます。

それがあなたが達成しようとしているものであれば、カスタムアニメーションを強制する必要はありません。bottomsheetdialog自体は、親Coordinator Layout

同じ動作を実装する方法のサンプルコードを次に示します。また、ボトムシートが全画面サイズまでドラッグされると、FloatingActionButtonが非表示になります。

  1. メインレイアウト内で使用するbottomsheetdialogを作成します

    public class CustomBottomDialog extends BottomSheetDialogFragment {
    
    String mSomeName;
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // if some arguments are passed from the calling activity 
        mSomeName = getArguments().getString("some_name");
    
    
    }
    
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View bottomSheet = inflater.inflate(R.layout.bottomsheet_layout, container, false);
         // initialise your bottomsheet_layout items here 
        TextView tvName = bottomSheet.findViewById(R.id.display_name);
        tvName.setText(mSomeName); 
        tvName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               // do something here
                ((MainActivity)getActivity()).doSomething();
            }
        });
    
        return bottomSheet;
    }
    }
    
  2. bottomsheet_layout:

    <Android.support.design.widget.CoordinatorLayout 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">
    
    <Android.support.design.widget.FloatingActionButton
    Android:id="@+id/nav"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:src="@drawable/navigation_tilt_grey"
    app:backgroundTint="@color/colorAccent"
    app:elevation="3dp"
    app:fabSize="normal"
    Android:layout_marginEnd="@dimen/activity_horizontal_margin"
    app:layout_anchor="@+id/live_dash"
    app:layout_anchorGravity="top|right" />
    
    <!--BottomSheet-->
    
    <Android.support.v4.widget.NestedScrollView
    Android:id="@+id/live_dash"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:background="#F3F3F3"
    Android:clipToPadding="true"
    app:layout_behavior="Android.support.design.widget.BottomSheetBe 
    havior"
    tools:layout_editor_absoluteY="150dp">
    
    <!--Include your items here, the height of all items combined
    will take the main screen layout size with animation-->
    
    </Android.support.v4.widget.NestedScrollView>
    
    </Android.support.design.widget.CoordinatorLayout>
    
  3. アクティビティからこのBottomSheetを呼び出す:

    public void notifyBottomSheet(String somename){
    
    BottomSheetDialogFragment customDialogFragment = new CustomBottomDialog();
    Bundle args = new Bundle();
    args.putString("some_name", somename);
    customDialogFragment.setArguments(args);
    customDialogFragment.show(getSupportFragmentManager(), customDialogFragment.getTag());
    customDialogFragment.setCancelable(false); // if you don't wish to hide
    }
    

    これがあなたが達成しようとしていることを解決することを願っています。

1
Prashant Kumar
## Translation Animation ##
<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:interpolator="@Android:anim/accelerate_decelerate_interpolator"
    Android:fillAfter="true"
    >
    <translate
        Android:fromYDelta="100%p"
        Android:toYDelta="-30%p"
        Android:duration="900" />
</set>

## 主な活動 ##

@Override
protected void onResume() {
    super.onResume();
    Animation am= AnimationUtils.loadAnimation(this,R.anim.fadeout);
    tv5.startAnimation(am);
    Animation myanim= AnimationUtils.loadAnimation(this,R.anim.translate);
    tv1.startAnimation(myanim);
    myanim.setStartOffset(500);
    Animation animation= AnimationUtils.loadAnimation(this,R.anim.translate);
    animation.setStartOffset(1000);
    tv2.startAnimation(animation);
    Animation an= AnimationUtils.loadAnimation(this,R.anim.translate);
    an.setStartOffset(1500);
    tv3.startAnimation(an);
    Animation ab= AnimationUtils.loadAnimation(this,R.anim.translate);
    ab.setStartOffset(2000);
    tv4.startAnimation(ab);
    Animation ac= AnimationUtils.loadAnimation(this,R.anim.fadein);
    ac.setStartOffset(2500);
    btn1.startAnimation(ac);
}
0
akshat saini

画面の下部から何かを簡単にスライドさせるには、次のようなコードを使用できます。

final int activityHeight = findViewById(Android.R.id.content).getHeight();
cardContainer.animate().yBy(activityHeight - cardContainer.getY()).setDuration(SLIDE_OUT_DURATION);

ここで、cardContainerは、画面からスライドさせようとしているビューです。

完全な例については、こちらをご覧ください ブログ投稿translationYの代わりにyByを使用することもできます。別のより一般的な方法は、次のコードを使用することです。

public static ViewPropertyAnimator slideOutToBottom(Context ctx, View view) {
    final int screenHeight = ctx.getResources().getDisplayMetrics().heightPixels;
    int[] coords = new int[2];
    view.getLocationOnScreen(coords);
    return view.animate().translationY(screenHeight - coords[Y_INDEX]).setDuration(SLIDE_OUT_DURATION);
}

public static ViewPropertyAnimator slideInFromBottom(Context ctx, View view) {
    final int screenHeight = ctx.getResources().getDisplayMetrics().heightPixels;
    int[] coords = new int[2];
    view.getLocationOnScreen(coords);
    view.setTranslationY(screenHeight - coords[Y_INDEX]);
    return view.animate().translationY(0).setDuration(SLIDE_IN_DURATION).setInterpolator(new OvershootInterpolator(1f));
}
0

それがあなたが望むものかどうかはわかりませんが、おそらくトランジションを使用する代わりに、関数animate()を使用できます。この関数を使用すると、アニメーションに関するすべてのもの(時間、可視性など) 。

0
oumaya saratoon