在有些桌面軟體或應用程式中,會看到可由螢幕下方拖拉出畫面的效果 (如Google Map),像這樣↓↓

這邊介紹簡單的製作方式:
首先以 GitHub 上的 PixelSlide 專案作為範例
原理就是在 CoordinatorLayout 中加入 include 區域,然後將另一個 view 引導進來
主要程式碼說明如下:
public class MainActivity extends AppCompatActivity {
private View mBottomSheet;
private BottomSheetBehavior mBottomSheetBehavior;
private ExpandIconView mExpandIconView;
private float mSlideOffset = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViews();
setUpViews();
}
private void findViews() {
mBottomSheet = findViewById(R.id.bottom_sheet);
//這邊是初始化拖拉畫面中的元件
mExpandIconView = (ExpandIconView) mBottomSheet.findViewById(R.id.expandIconView);
}
private void setUpViews() {
//設定箭頭icon的狀態(套件)
mExpandIconView.setState(ExpandIconView.LESS, true);
//將mBottomSheet綁定給BottomSheetBehavior
mBottomSheetBehavior = BottomSheetBehavior.from(mBottomSheet);
//監聽BottomSheetBehavior拖動過程
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
//拖動的畫面狀態切換
if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
mExpandIconView.setState(ExpandIconView.LESS, true);
} else if (newState == BottomSheetBehavior.STATE_EXPANDED) {
mExpandIconView.setState(ExpandIconView.MORE, true);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, final float slideOffset) {
//這裡是整個拖動過程
mSlideOffset = slideOffset;
//控制箭頭套件的狀態而已
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
float dis = (mSlideOffset - slideOffset) * 10;
if (dis > 1) {
dis = 1;
} else if (dis < -1) {
dis = -1;
}
if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_DRAGGING) {
mExpandIconView.setFraction(.5f + dis * .5f, false);
}
}
}, 150);
}
});
//設定拖拉畫面收起時的突出大小
//這邊將dp轉換為px
mBottomSheetBehavior.setPeekHeight((int) convertDpToPixel(70, this));
//設定拖拉視窗的狀態 (STATE_COLLAPSED = 縮小, STATE_EXPANDED = 展開)
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
//dp轉px
public float convertDpToPixel(float dp, Context context) {
return dp * (getDisplayMetrics(context).densityDpi / 160f);
}
public DisplayMetrics getDisplayMetrics(Context context) {
Resources resources = context.getResources();
return resources.getDisplayMetrics();
}
}
這邊可以來做一些修改,讓他更貼近實際使用。
-
設計圓角,讓畫面更好看

在res資料夾筆下新增drawable資料夾,裡面新增一個xml,例:drawable_round_edge.xml
在檔案中新增一個<shape>,設定背景顏色與圓角大小,如下
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--填充設定-->
<solid android:color="#ff333333"/>
<!--圓角設定-->
<corners
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
</shape>
在專案的bottom_sheet layout中,也就是你的拖拉畫面佈局中,在最頂層View設定背景為drawable_round_edge.xml
-
限制展開大小
在預設的設計中,展開拖拉畫面布局時,會蓋住整個畫面,就像下圖一樣。

大部分會希望能看到部分背景,所以我們要限制拖拉畫面的高度,讓他可以看見部分背景佈局,如下圖。

增加程式碼功能:
首先增加一個計算畫面高度的功能:
public float convertPercentageToPixel(float percentage, Context context) {
return getDisplayMetrics(context).heightPixels * percentage;
}
這邊會抓取app畫面的高度,然後再乘以input進來的percentage比例,結果就是我們想要顯示的比例高度(上圖範例為占用70%)
然後在findViews()中增加拖拉布局的頂層畫面物件:
private void findViews() {
mBottomSheet = findViewById(R.id.bottom_sheet);
mExpandIconView = (ExpandIconView) mBottomSheet.findViewById(R.id.expandIconView);
//---加入此行---
mbottom_sheet = (FrameLayout) mBottomSheet.findViewById(R.id.bottom_sheet);
}
接下來在setUpViews()中設定mbottom_sheet布局的高度:
private void setUpViews() {
//---加入這區---
//取得View的參數
ViewGroup.LayoutParams params = mbottom_sheet.getLayoutParams();
//設定View的高度,按比例計算
params.height = (int)convertPercentageToPixel(0.7f, this);
//設定View的參數
mbottom_sheet.setLayoutParams(params);
//---加入這區---
mExpandIconView.setState(ExpandIconView.LESS, true);
mBottomSheetBehavior = BottomSheetBehavior.from(mBottomSheet);
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
mExpandIconView.setState(ExpandIconView.LESS, true);
} else if (newState == BottomSheetBehavior.STATE_EXPANDED) {
mExpandIconView.setState(ExpandIconView.MORE, true);
}
...
...
這樣在拖拉佈局產生之後,就會按畫面高度比例去設定拖拉布局的最大高度了!
-END-
發佈留言