私のアプリケーションでは、うまく機能するボトムシート(サポートライブラリから)を使用しています。次に、シートが上にドラッグされている間にレイアウトの変更をアニメートしたいと思います。このために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
も作成しました。私の問題は、Transition
がslideOffset
パラメーター(0-1の範囲)に基づいている必要があるが、TransitionManager
はAnimation
クラスを使用することです通常はAndroidの時間ベースの背景。
カスタムIntapolatorを作成しようとしましたが、これは正しく機能しません。では、時間ではなく外部変数に基づくTransition
を作成するにはどうすればよいですか?
あなたの説明に基づいて、Googleマップのボトムシートの動作のようなものを達成しようとしていると思います。 bottomsheetが上にドラッグされると、レイアウトが変更されます。
それがあなたが達成しようとしているものであれば、カスタムアニメーションを強制する必要はありません。bottomsheetdialog自体は、親Coordinator Layout。
同じ動作を実装する方法のサンプルコードを次に示します。また、ボトムシートが全画面サイズまでドラッグされると、FloatingActionButtonが非表示になります。
メインレイアウト内で使用する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;
}
}
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>
アクティビティからこの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
}
これがあなたが達成しようとしていることを解決することを願っています。
## 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);
}
画面の下部から何かを簡単にスライドさせるには、次のようなコードを使用できます。
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));
}
それがあなたが望むものかどうかはわかりませんが、おそらくトランジションを使用する代わりに、関数animate()
を使用できます。この関数を使用すると、アニメーションに関するすべてのもの(時間、可視性など) 。