Lollipopツールバーのアニメーション(Telegramアプリ)の展開・折りたたみについて
質問
ツールバーの展開・折りたたみのアニメーションがどのように行われているのか、知りたいです。Telegram アプリの設定を見てもらうと、リストビューとツールバーがあることがわかると思います。下にスクロールするとツールバーが折りたたまれ、上にスクロールするとツールバーが展開されます。また、プロフィール写真とFABのアニメーションがあります。どなたか手がかりをお持ちの方はいらっしゃいますか?その上にすべてのアニメーションを構築しているのでしょうか?もしかしたら、私は新しいAPIやサポートライブラリから何かを見逃しているかもしれません。
Google カレンダー アプリで、スピナー (スピナーではないと思いますが、そのように見えます) を開くと、同じ動作に気づきました。ツール バーが展開され、上にスクロールすると、ツール バーが折りたたまれます。
はっきり言いますが、QuickReturnメソッドは必要ありません。おそらく Telegram アプリが似たようなものを使用していることは知っています。私が必要とする正確なメソッドは、Google カレンダー アプリの効果です。私は、以下の方法で試してみました。
android:animateLayoutChanges="true"
で、expandメソッドはかなりうまく動作します。しかし、明らかに、私がListViewを上にスクロールした場合、ツールバーは折りたたまれません。
を追加することも考えました。
GestureListener
を追加することも考えましたが、これを実現するAPIやより簡単な方法があれば知りたいのです。
ないのであれば、やはり
GestureListener
. うまくいけば、アニメーションの効果がスムーズに出るかもしれません。
ありがとうございます。
どのように解決するのですか?
編集する。
Android Designサポートライブラリがリリースされたので、より簡単に解決できるようになりました。確認 joaquin さんの回答
--
おそらく他にも多くの解決策があると思いますが、私の場合はこれでうまくいきました。
-
まず最初に
Toolbar
を透明な背景で表示します。展開する & 折り畳むToolbar
は実際には の偽物です。 の下にあるもので、透明なToolbar
. (下の最初のスクリーンショット - 余白のあるもの - を見れば、これがTelegramでのやり方でもあることがわかります)。私たちが保持するのは、実際の
Toolbar
に対してNavigationIcon
で、オーバーフローのMenuItem
.<イグ
-
2 番目のスクリーンショットの赤い四角の中にあるものすべて (つまり、偽の
Toolbar
とFloatingActionButton
) は実際には ヘッダ に追加するもので、設定にListView
(またはScrollView
).ですから、このヘッダのレイアウトを別のファイルに作成する必要があります。それは、次のようなものです。
<!-- The headerView layout. Includes the fake Toolbar & the FloatingActionButton --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <RelativeLayout android:id="@+id/header_container" android:layout_width="match_parent" android:layout_height="@dimen/header_height" android:layout_marginBottom="3dp" android:background="@android:color/holo_blue_dark"> <RelativeLayout android:id="@+id/header_infos_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:padding="16dp"> <ImageView android:id="@+id/header_picture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginRight="8dp" android:src="@android:drawable/ic_dialog_info" /> <TextView android:id="@+id/header_title" style="@style/TextAppearance.AppCompat.Title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/header_picture" android:text="Toolbar Title" android:textColor="@android:color/white" /> <TextView android:id="@+id/header_subtitle" style="@style/TextAppearance.AppCompat.Subhead" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/header_title" android:layout_toRightOf="@+id/header_picture" android:text="Toolbar Subtitle" android:textColor="@android:color/white" /> </RelativeLayout> </RelativeLayout> <FloatingActionButton android:id="@+id/header_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right" android:layout_margin="10dp" android:src="@drawable/ic_open_in_browser"/> </FrameLayout>
(ただし,fabが2をまたぐ場合は負のマージン/パディングを使用することができます。
Views
) -
さて、ここからが面白いところです。私たちの偽の
Toolbar
の拡張をアニメーション化するために、私たちはListView
onScrollListener
.// The height of your fully expanded header view (same than in the xml layout) int headerHeight = getResources().getDimensionPixelSize(R.dimen.header_height); // The height of your fully collapsed header view. Actually the Toolbar height (56dp) int minHeaderHeight = getResources().getDimensionPixelSize(R.dimen.action_bar_height); // The left margin of the Toolbar title (according to specs, 72dp) int toolbarTitleLeftMargin = getResources().getDimensionPixelSize(R.dimen.toolbar_left_margin); // Added after edit int minHeaderTranslation; private ListView listView; // Header views private View headerView; private RelativeLayout headerContainer; private TextView headerTitle; private TextView headerSubtitle; private FloatingActionButton headerFab; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.listview_fragment, container, false); listView = rootView.findViewById(R.id.listview); // Init the headerHeight and minHeaderTranslation values headerHeight = getResources().getDimensionPixelSize(R.dimen.header_height); minHeaderTranslation = -headerHeight + getResources().getDimensionPixelOffset(R.dimen.action_bar_height); // Inflate your header view headerView = inflater.inflate(R.layout.header_view, listview, false); // Retrieve the header views headerContainer = (RelativeLayout) headerView.findViewById(R.id.header_container); headerTitle = (TextView) headerView.findViewById(R.id.header_title); headerSubtitle = (TextView) headerView.findViewById(R.id.header_subtitle); headerFab = (TextView) headerView.findViewById(R.id.header_fab);; // Add the headerView to your listView listView.addHeaderView(headerView, null, false); // Set the onScrollListener listView.setOnScrollListener(this); // ... return rootView; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // Do nothing } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { Integer scrollY = getScrollY(view); // This will collapse the header when scrolling, until its height reaches // the toolbar height headerView.setTranslationY(Math.max(0, scrollY + minHeaderTranslation)); // Scroll ratio (0 <= ratio <= 1). // The ratio value is 0 when the header is completely expanded, // 1 when it is completely collapsed float offset = 1 - Math.max( (float) (-minHeaderTranslation - scrollY) / -minHeaderTranslation, 0f); // Now that we have this ratio, we only have to apply translations, scales, // alpha, etc. to the header views // For instance, this will move the toolbar title & subtitle on the X axis // from its original position when the ListView will be completely scrolled // down, to the Toolbar title position when it will be scrolled up. headerTitle.setTranslationX(toolbarTitleLeftMargin * offset); headerSubtitle.setTranslationX(toolbarTitleLeftMargin * offset); // Or we can make the FAB disappear when the ListView is scrolled headerFab.setAlpha(1 - offset); } // Method that allows us to get the scroll Y position of the ListView public int getScrollY(AbsListView view) { View c = view.getChildAt(0); if (c == null) return 0; int firstVisiblePosition = view.getFirstVisiblePosition(); int top = c.getTop(); int headerHeight = 0; if (firstVisiblePosition >= 1) headerHeight = this.headerHeight; return -top + firstVisiblePosition * c.getHeight() + headerHeight; }
このコードには私がテストしていない部分があるので、自由に間違いを指摘してください。しかし、全体として、私はこのソリューションが動作することを知っています、私はそれが改善されると確信しています。
EDIT 2:
上のコードにいくつか間違いがあったので(今日までテストしていなかったのですが・・・)、数行変更して動くようにしました :
- minHeaderHeight を置き換えて、minHeaderTranslation という別の変数を導入しました。
-
ヘッダーViewに適用されるY変換の値を、:
headerView.setTranslationY(Math.max(-scrollY, minHeaderTranslation));
になります。
headerView.setTranslationY(Math.max(0, scrollY + minHeaderTranslation));
前の表現が全く機能していませんでした、申し訳ありません...。
-
比率の計算も変更され、ツールバーの下部 (画面の上部ではなく) から完全に展開されたヘッダーに展開されるようになりました。
関連
-
[解決済み] アンドロイド アニメーションの拡大・縮小
-
[解決済み] AndroidのPull-to-Refreshの実装方法
-
[解決済み】Android API 21 ツールバーパディング
-
[解決済み] ViewPagerのアイテムを強制的に再インスタンス化する方法 [重複].
-
[解決済み] アンドロイドアプリのユーザーデータを消去する
-
[解決済み] onCreate(Bundle savedInstanceState)とは?
-
[解決済み] 文字サイズとアンドロイドの画面サイズの違い
-
[解決済み] APKが署名済みかデバッグビルドかを確認するには?
-
[解決済み] react nativeアプリのバージョン番号を更新する方法
-
[解決済み] Android APKファイルの中身を見るには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] AndroidにおけるViewPager2の適切な実装
-
[解決済み] Androidの連絡先リストを呼び出すには?
-
[解決済み] Android Debug Bridgeでアプリケーションのインストール時にINSTALL_FAILED_VERSION_DOWNGRADEを無視する方法はありますか?
-
[解決済み] AppCompat-v7 21でアクションバー/ツールバーにアイコンを表示する。
-
[解決済み] Android Studio - あいまいなメソッド呼び出し getClass()
-
[解決済み] アンドロイドでシェイクを検出するには?
-
[解決済み] Android端末がHDPI画面かMDPI画面かを確認する方法は?
-
[解決済み] EditTextをReadOnlyにする
-
[解決済み] Gradleでビルドタイプを使用し、ContentProviderを使用する同じアプリを1つのデバイスで実行する。
-
[解決済み] Google Play ストア内部テストのロールアウトが開始できない