Material DesignシリーズのBehaviorがAndroidを実現するトップページ


このブログの目的:トップページを上にスライドさせる時に、アニメはToolbar、Flocation ActButon、Tabナビゲーションを隠します。降りる時に表示されます。もしあなたの期待と違ったら、見なくてもいいです。貴重な時間を無駄にしないでください。
効果のプレビュー
知得効果:

このブログの効果:

今日の効果のソースコードは文章の最後にリンクされます。
分析を実現する
この効果は実现するのは难しくないですが、ユーザーの指が滑って画面に下の内容が表示されると、Toolbar、Tabナビゲーション、FABを隠して、より大きな空间を作ってコンテンツを表示し、ユーザーを爽快にします。簡単で乱暴ですが、これが私たちの目的です。
まず頭のToolbarです。これはもちろんです。基本的にできます。できない人は気軽に私のブログを見てください。デモもこの効果があります。まるで小学校レベルです。
その次にFABの表示と隠れを見にきて、知っているのは並進するので、私達はここで優良化の変化をして、もちろん並進するのもできて、もしあなたは私のMaterial Designシリーズを見たことがあるならば、Behaviorをカスタマイズして上にスライドして上に戻るボタンを表示します。このブログの話。私達のFABのアニメーションは隠れて表示するのも前のブログの原理を使うので、1篇のブログを見ていない学友は振り返って見なければならなくて、ここは詳しく述べていません。
最後に下のTabナビゲーションの隠しと表示を見にきました。これは確かに実用的に並進したほうがいいですよね。でも、もしあなたが私のMaterial Designシリーズを見たことがあれば、BehaviorのBottom Sheet BehaviorとBottom Sheet Dialogのこのブログを実現するのも難しくないと信じています。次の文章を読む前にこの文章を読むように強く勧めます。でないと本当に続けて読むことができません。
コード量はまだ少ないです。主にBehavior原理、BehaviorとCoordinasolayoutはどうやって結合して使うのですか?そして、上の二つのブログを読むことを強く勧めます。
……
はい、5分が過ぎました。上記の2つのブログを速読したと思います。最初のFABのブログでは、指を上に向けてスライドさせるとFABが上に戻ると表示されますが、ここでは反対です。上に滑ってFABを隠します。原理解釈の一節をよく読んだら、あるいはデモを実行したことがあります。この効果はsoeasuyでしょう。二番目のブログでもこのTabナビゲーションを隠す方法と表示する方法について言及しましたが、学生の中には今日のブログはもう終わったという人もいますよね?答えはもちろんNoです。じゃないとブログをもう一回開けません。これについて話します。
なぜですか?まだ難しいところがありますが、難しいところはどこにありますか?上記の二つのBehaviorはどうやってCoordinasolayoutと結合して使うかということです。二つの効果を同時に実現します。そして、Bottom Sheet BehaviorはTabナビゲーションを隠して表示します。この中に入る前にButtonを使ってコントロールしました。CoordinatoLayoutのContentViewがスライドする時のダイナミックな表示とTabナビゲーションを隠すにはどうすればいいですか?
これから本物の材料を注文して、みんなを連れてコードをかき集めます。
ページレイアウト
上の引用文と紹介により、FABの表示と隠蔽はカスタムBehaviorで実現され、TabナビゲーションはBottom Sheet Behaviorで実現されることが分かりました。

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <android.support.design.widget.AppBarLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:theme="@style/AppTheme.AppBarOverlay">

  <android.support.v7.widget.Toolbar
   android:id="@+id/toolbar"
   android:layout_width="match_parent"
   android:layout_height="?attr/actionBarSize"
   app:layout_scrollFlags="scroll|enterAlways|snap"
   app:popupTheme="@style/AppTheme.PopupOverlay" />
 </android.support.design.widget.AppBarLayout>

 <android.support.v7.widget.RecyclerView
  android:id="@+id/recyclerView"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:layout_behavior="@string/appbar_scrolling_view_behavior" />

 <LinearLayout
  android:id="@+id/tab_layout"
  android:layout_width="match_parent"
  android:layout_height="?actionBarSize"
  android:layout_alignParentBottom="true"
  android:background="@android:color/white"
  app:layout_behavior="@string/bottom_sheet_behavior">

  <Button
   android:layout_width="0dp"
   android:layout_height="match_parent"
   android:layout_weight="1"
   android:text="  " />

  <Button
   android:layout_width="0dp"
   android:layout_height="match_parent"
   android:layout_weight="1"
   android:text="  " />

  <Button
   android:layout_width="0dp"
   android:layout_height="match_parent"
   android:layout_weight="1"
   android:text="  " />

  <Button
   android:layout_width="0dp"
   android:layout_height="match_parent"
   android:layout_weight="1"
   android:text="  " />
 </LinearLayout>

 <android.support.design.widget.FloatingActionButton
  android:id="@+id/fab"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="bottom|end"
  android:layout_marginBottom="70dp"
  android:layout_marginEnd="16dp"
  android:layout_marginRight="16dp"
  android:src="@mipmap/ic_action_new"
  app:layout_behavior="@string/scale_down_show_behavior"
  app:layout_scrollFlags="scroll|enterAlways|snap" />
</android.support.design.widget.CoordinatorLayout>
まだ少し説明します。コンテンツエリアはRecyclerViewで、BehaviorはdesignのSrollingView Behaviorを使用しています。
ap:layout_behavior=「@string/appbar_」scrolling_viewbehavior「
そして、Linear Layoutで使われているBehaviorはdesignのBottom Sheet Behaviorです。
ap:layout_behavior=「@string/bottom_」sheet_behavior「
最後のFloat ingAction Buttonは、私達のカスタムScaleDown Show Behaviorを使っています。
ap:layout_behavior=「@string/scale_」ダウンタウンショーbehavior「
他の二つは全部designが持参したものです。Float at ingActionのScaleDown Show Behaviorだけが私達のカスタマイズが必要です。それではScaleDown Show Behaviorを実現します。
BehaviorをカスタマイズしてFABのアニメーション制御を実現します。
ここでまたカスタムBehaviorについて話しました。まず、ユーザーの指がスクリーン上で滑り、FABを隠し、より多くの位置を残してユーザーに与えます。
ここはまだFloat at ingAction.Behaviorを継承しています。

public class ScaleDownShowBehavior extends FloatingActionButton.Behavior {
 public ScaleDownShowBehavior(Context context, AttributeSet attrs) {
  super();
 }
}
ここでは私達のスライドの方向は相変わらずです。縦方向のスライドを監督します。

@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, ...) {
 return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
この方法を少し変えます。私達はスライドを始める時にこの方法を変えます。

@Override
//           
private boolean isAnimatingOut = false;

public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
 if ((dyConsumed > 0 || dyUnconsumed > 0) && !isAnimatingOut
 && child.getVisibility() == View.VISIBLE) {//     ,  FAB
  AnimatorUtil.scaleHide(child, listener);
 } else if ((dyConsumed < 0 || dyUnconsumed < 0) && child.getVisibility() != View.VISIBLE) {
  AnimatorUtil.scaleShow(child, null);//     ,  FAB
 }
}

private ViewPropertyAnimatorListener listener = new ViewPropertyAnimatorListener() {
 @Override
 public void onAnimationStart(View view) {
  isAnimatingOut = true;
 }

 @Override
 public void onAnimationEnd(View view) {
  isAnimatingOut = false;
  view.setVisibility(View.GONE);
 }

 @Override
 public void onAnimationCancel(View arg0) {
  isAnimatingOut = false;
 }
};
はい、コードがとても少なくて完成しました。私達はstring.xmlの中で定義します。先ほど私達が引用した変数@string/scale_ダウンタウンショーbehavior:
com.yanzhenjie.definebehavior.behavior.ScaleDownShowBehavior
ああ、興奮しました。早く運転します。でも、でも。運行後に鬼に会ったことを発見しました。FABだけが表示と隠しに従っています。Tabナビゲーションが全然見えません。厳振傑さんは人をだましていますか?はははははは、また私の事細かな話を聞いてください。
ScaleDown Show Behaviorのview表示/非表示をモニターすることにより、Tabナビゲーションバーを制御する。
実際にMaterial Designシリーズを見たら、BehaviorのBottom Sheet BehaviorとBottom Sheet Dialogという文章を見た学生が発見します。Bottom Sheet Behaviorのコントロールでデフォルトはすべて隠しています。その表示を制御するためにその方法を呼び出さなければなりません。だから、ここではCoordinatoLayoutのContentViewをスクロールする時にBottom SheetBehaviorを呼び出す方法が必要です。それを依存するViewを表示し、隠します。
ScaleDown Show Behaviorはシステムに自動的に呼び出されました。また、Viewの隠蔽と表示をトリガしました。CoordinatoLayoutこの商品は私達に自動的にBottom Sheet Behaviorを呼び出さなかったです。どうすればいいですか?忘れていないなら、私達がカスタマイズしたScaleDown Show Behaviorの時に、one NestedScrrollの方法の中にFABの表示を呼び出して隠しているところがあります。だから、ここでリベートを追加して、外部にその動作をモニターしてもらいます。Bottom Sheet Behaviorを制御できますか?まだ向明していないならコードを見ます。
まずScaleDown Show Behaviorの中でListenerを決めます。

//          。
public interface OnStateChangedListener {
 void onChanged(boolean isShow);
}

次に、ScaleDown Show Behaviorのone NestedScrroll()方法でフィードバックする:

private OnStateChangedListener mOnStateChangedListener;

public void setOnStateChangedListener(OnStateChangedListener mOnStateChangedListener) {
 this.mOnStateChangedListener = mOnStateChangedListener;
}

@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
 if ((dyConsumed > 0 || dyUnconsumed > 0) && !isAnimatingOut
 && child.getVisibility() == View.VISIBLE) {//   
  AnimatorUtil.scaleHide(child, viewPropertyAnimatorListener);
  if (mOnStateChangedListener != null) {
   mOnStateChangedListener.onChanged(false);
  }
 } else if ((dyConsumed < 0 || dyUnconsumed < 0) && child.getVisibility() != View.VISIBLE) {
  AnimatorUtil.scaleShow(child, null);
  if (mOnStateChangedListener != null) {
   mOnStateChangedListener.onChanged(true);
  }
 }
}

完璧ですね。来てください。モニターを設置します。このBehaviorをFABからどうやって持って行けばいいですか?ちょっと見てください。次の分析を見てください。柳陰花明さんにまた村があるように保証します。
FABのBehaviorの対象を取得し、Bottom Sheet BehaviorのViewの表示/非表示をモニターで制御する。
私達はViewにBehaviorのオブジェクトを設定する時はxmlに設定することを知っています。だからBehaviorはViewのLayoutParaams属性ですよね?はははははは分かりましたか?そしてBehaviorはまたCoordinaso Layoutと結合して使用しなければなりません。そうでなければ、このViewもCoordinato Layoutの子Viewでなければなりません。だから、ScaledowShow Behaviorの中で次のような静的な方法が生まれました。

public static <V extends View> ScaleDownShowBehavior from(V view) {
 ViewGroup.LayoutParams params = view.getLayoutParams();
 if (!(params instanceof CoordinatorLayout.LayoutParams)) {
  throw new IllegalArgumentException("  View  CoordinatorLayout  View");
 }
 CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params).getBehavior();
 if (!(behavior instanceof ScaleDownShowBehavior)) {
  throw new IllegalArgumentException("  View Behaviro  ScaleDownShowBehavior");
 }
 return (ScaleDownShowBehavior) behavior;
}

ですから、私たちはActivityにいます。

private BottomSheetBehavior mBottomSheetBehavior;
@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.zhihu_main);

 ScaleDownShowBehavior scaleDownShowFab = ScaleDownShowBehavior.from(FAB);
 scaleDownShowFab.setOnStateChangedListener(onStateChangedListener);
 mBottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.tab_layout));
}

private OnStateChangedListener onStateChangedListener = new OnStateChangedListener() {
 @Override
 public void onChanged(boolean isShow) {
  mBottomSheetBehavior.setState(
  isShow ? BottomSheetBehavior.STATE_EXPANDED
  : BottomSheetBehavior.STATE_COLLAPSED);
 }
};

えっと、知らないうちに私達の効果を実現しました。ここで一番重要なのはオンストップのChangedListenerです。ここでTabナビゲーションの隠蔽と表示を実現しました。
ページ初期化が完了したら、Tabナビゲーションを表示します。
上記では、Bottom Sheet Behaviorの属性を付加したViewはデフォルトでは非表示です。だから、私達はページ初期化の時に私達のTabナビゲーションを表示します。

private boolean initialize = false;

@Override
public void onWindowFocusChanged(boolean hasFocus) {
 super.onWindowFocusChanged(hasFocus);
 if (!initialize) {
  initialize = true;
  mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
 }
}

ソースのダウンロード:http://xiazai.jb51.net/201609/yuanma/AndroidBehavior(jb 51.net)rar
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。