趁著UI妹子還沒有把圖切好,我這幾天簡直閑得不行莲镣,所以得空學(xué)習(xí)一下CoordinatorLayout
的使用,當(dāng)然這里不會是想特地寫一篇文章來介紹它的基本用法,因為這個在網(wǎng)上有太多的資料刹孔。學(xué)習(xí)完基礎(chǔ)我們就可以深入其中,學(xué)習(xí)其精髓小泉。那么CoordinatorLayout
最精髓的地方是什么呢芦疏?就是Behaviour。
那么什么是Behaviour呢微姊?可以先看看以下博客
Android——CoordinatorLayout之Behavior入門學(xué)習(xí)(上)
Android——CoordinatorLayout之Behavior入門學(xué)習(xí)(下)
感謝博主郭神酸茴。
Behaviour使用
一、仿知乎首頁
項目中將會使用到知乎首頁的效果
我們可以看到兢交,底部菜單Tab會隨著滑動隱藏和顯示
不使用Behaviour
我在第一次思考時是不使用Behaviour薪捍,監(jiān)聽AppBarLayout滑動距離進(jìn)行操作:
bar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
///下拉:0~-height,上拉:-height~0
if (verticalOffset != 0) {
if (height != 0) {
Log.d("Activity", "onOffsetChanged: vertaicalOffset =====" + verticalOffset);
//通過滑動距離跟高度計算得到percent值
float i = (height + verticalOffset) / height;
Log.d("Activity", "onOffsetChanged: i=====" + i);
float alpha = 255 * i / 255;
Log.d("Activity", "onOffsetChanged: alpha === " + alpha);
ViewGroup.LayoutParams params = mBottom.getLayoutParams();
//通過percent值對底部Tab的LayoutParams進(jìn)行修改
params.height = (int) (height * alpha);
mBottom.requestLayout();
}
}
}
});```
這時我遇到一個小問題配喳,就是在快速滑動的時候底部Tab計算會跟不上滑動的速度導(dǎo)致底部Tab的高度不正確
(如下圖)

那么我是怎樣解決的呢酪穿?
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
Log.d("Activity", "onScrollStateChanged: newState===" + newState);
// LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int position = layoutManager.findFirstCompletelyVisibleItemPosition();
Log.d("Activity", "onScrollStateChanged: completeItemPosition ====" + position);
if (position == 0 && newState == RecyclerView.SCROLL_STATE_IDLE) {
if (mBottom.getHeight() != height) {
mBottom.getLayoutParams().height = (int) height;
mBottom.requestLayout();
}
}
}
});```
我這里是通過監(jiān)聽recyclerView的顯示item來強(qiáng)制修改,達(dá)到目的(這里提供一個解決思路晴裹,非最佳)
使用Behaviour
簡單自定義一個Behaviour即可達(dá)到效果
/**
* Created by AmatorLee on 2017/7/18.
*/
public class FootBehaviour extends CoordinatorLayout.Behavior<View> {
public FootBehaviour(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return dependency instanceof AppBarLayout;
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
//通過AppBarLayout的滑動距離計算percent
float scaleY = Math.abs(dependency.getY()) / dependency.getHeight();
//通過percent動態(tài)移動我們的view被济,注意是移動不是修改
child.setTranslationY(child.getHeight() * scaleY);
return true;
}
}```
看看效果

#####二、仿魅族應(yīng)用商店應(yīng)用詳情效果
作為一個多年的魅族手機(jī)使用者涧团,看起來魅族的應(yīng)用商店也挺不錯的只磷,來看看要實現(xiàn)的效果(**注:實現(xiàn)效果而非實現(xiàn)實現(xiàn)界面**)

1. 思路一:使用Activity實現(xiàn),但是這樣需要解決的問題有:
1. Activity進(jìn)場/出場動畫
2. 對于滑動的監(jiān)聽
3. 對狀態(tài)欄的動態(tài)改變
2. 思路二:由于我們這邊使用的是Behaviour泌绣,而系統(tǒng)給我們提供了一個```BottomSheetBehavior```應(yīng)該可以完美的給我們解決滑動的問題钮追,但是Activity方面的問題依然存在,然后找到了一個強(qiáng)大的Dialog(```BottomSheetDialog```)和一個DialogFragment(```BottomSheetDialogFragment```),,以我夜觀天象應(yīng)該這個就是實現(xiàn)了``````BottomSheetBehavior```的View阿迈,很好很強(qiáng)大元媚。
我們來看看我們是怎樣是實現(xiàn)的:
/**
* BottomSheetDialog
*/
Button btnShowDialog = (Button) findViewById(R.id.bottom_pull_sheet);
mDatas = new ArrayList<>();
View inflate = getLayoutInflater().inflate(R.layout.dialog_bottom_sheet, null);
mLeftIcon = inflate.findViewById(R.id.delete);
mLeftIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mBottomSheetDialog != null && mBottomSheetDialog.isShowing()) {
mBottomSheetDialog.dismiss();
}
}
});
RecyclerView recyclerView = inflate.findViewById(R.id.recyclerView);
mDatas = new ArrayList<>();
for (int i = 0; i < 50; i++) {
mDatas.add("這是第" + i + "個數(shù)據(jù)");
}
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
recyclerView.setLayoutManager(new LinearLayoutManager(this));
Adapter adapter = new Adapter();
recyclerView.setAdapter(adapter);
mBottomSheetDialog = new BottomSheetDialog(this);
mBottomSheetDialog.setContentView(inflate);
View container = mBottomSheetDialog.getDelegate().findViewById(android.support.design.R.id.design_bottom_sheet);
final BottomSheetBehavior containerBehaviour = BottomSheetBehavior.from(container);
containerBehaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
Log.d(TAG, "onStateChanged: newState === " + newState);
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
mBottomSheetDialog.dismiss();
containerBehaviour.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
//強(qiáng)制修改彈出高度為屏幕高度的0.9倍,不做此操作僅僅有CollapSed/Expand兩種苗沧,就是0.5和1倍展開的效果
containerBehaviour.setPeekHeight((int) (0.9 * height));
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
Log.d("BottomBahaviour", "onSlide: slideOffset====" + slideOffset);
if (slideOffset == 1.0) {
mLeftIcon.setImageResource(R.drawable.back);
// containerBehaviour.setPeekHeight(height + getStatusBarHeight());
//修改狀態(tài)欄
mBottomSheetDialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mBottomSheetDialog.getWindow().setStatusBarColor(getResources().getColor(android.R.color.transparent));
try {
//修改魅族系統(tǒng)狀態(tài)欄字體顏色
WindowManager.LayoutParams lp = mBottomSheetDialog.getWindow().getAttributes();
Field darkFlag = WindowManager.LayoutParams.class
.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
Field meizuFlags = WindowManager.LayoutParams.class
.getDeclaredField("meizuFlags");
darkFlag.setAccessible(true);
meizuFlags.setAccessible(true);
int bit = darkFlag.getInt(null);
int value = meizuFlags.getInt(lp);
value |= bit;
meizuFlags.setInt(lp, value);
mBottomSheetDialog.getWindow().setAttributes(lp);
} catch (Exception e) {
}
}
} else {
mLeftIcon.setImageResource(R.drawable.icon_delete);
}
}
});
btnShowDialog.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!mBottomSheetDialog.isShowing()) {
containerBehaviour.setPeekHeight((int) (0.9 * height));
mBottomSheetDialog.show();
} else {
mBottomSheetDialog.dismiss();
}
}
});
class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(BottomActivity.this).inflate(R.layout.layout_item, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTvTip.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas == null && mDatas.size() < 0 ? 0 : mDatas.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView mTvTip;
public ViewHolder(View itemView) {
super(itemView);
mTvTip = (TextView) itemView.findViewById(R.id.tv_tips);
}
}
}
通過以上簡單的錯作即可實現(xiàn)我們想要的效果:

這是在模擬器上運行的結(jié)果刊棕,在魅族手機(jī)呢?

就這么簡單即可完美實現(xiàn)效果待逞。
#####總結(jié)
通過對Behaviour的學(xué)習(xí)很多看起來以前很難的效果我們都可以輕松實現(xiàn)鞠绰。如果你發(fā)現(xiàn)上面有任何錯漏,麻煩留言指出飒焦,同時我也會進(jìn)行自我完善蜈膨。
#####參考文章
[白底黑字屿笼!Android淺色狀態(tài)欄黑色字體模式](http://www.reibang.com/p/7f5a9969be53)
[Material Design系列](http://blog.csdn.net/yanzhenjie1003/article/details/52205665)