Android 动态更改底部挡板的高度
我使用的是谷歌最近发布的AppCompat v23.2的Android 动态更改底部挡板的高度,android,android-appcompat,Android,Android Appcompat,我使用的是谷歌最近发布的AppCompat v23.2的BottomSheetBehavior。我的底页的高度取决于底页内部显示的内容(类似于谷歌自己在地图应用程序中所做的) 它可以很好地处理最初加载的数据,但我的应用程序会在运行时更改显示的内容,当这种情况发生时,底部工作表仍保持原来的高度,这会导致底部未使用的空间或视图的剪切 是否有任何方法通知底部图纸布局重新计算展开状态所用的高度(当视图组的高度设置为匹配高度时)或手动设置所需高度 EDIT:我还试图手动调用ViewGroup及其父对象上
BottomSheetBehavior
。我的底页的高度取决于底页内部显示的内容(类似于谷歌自己在地图应用程序中所做的)
它可以很好地处理最初加载的数据,但我的应用程序会在运行时更改显示的内容,当这种情况发生时,底部工作表仍保持原来的高度,这会导致底部未使用的空间或视图的剪切
是否有任何方法通知底部图纸布局重新计算展开状态所用的高度(当视图组的高度设置为匹配高度时)或手动设置所需高度
EDIT:我还试图手动调用ViewGroup
及其父对象上的invalidate()
,但没有成功。您可以使用BottomSheetBehavior#setpeek height
来实现这一点
FrameLayout bottomSheet = (FrameLayout) findViewById(R.id.bottom_sheet);
BottomSheetBehavior<FrameLayout> behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setPeekHeight(newHeight);
我的RelativeLayout
与我的底页有相同的问题。不会重新计算高度。我不得不通过重新计算的新值来设置高度,然后调用BottomSheetBehavior.onLayoutChild
这是我的临时解决方案:
coordinatorLayout = (CoordinatorLayout)findViewById(R.id.coordinator_layout);
bottomSheet = findViewById(R.id.bottom_sheet);
int accountHeight = accountTextView.getHeight();
accountTextView.setVisibility(View.GONE);
bottomSheet.getLayoutParams().height = bottomSheet.getHeight() - accountHeight;
bottomSheet.requestLayout();
behavior.onLayoutChild(coordinatorLayout, bottomSheet, ViewCompat.LAYOUT_DIRECTION_LTR);
当我在底部工作表中使用recyclerview时,我也面临着同样的问题,而这些项目是动态变化的。正如@sosite在他的评论中提到的,这个问题已经被记录下来,他们已经在最新版本中修复了它。
只需将您的设计支持库更新到24.0.0版本并进行检查。尽管问题已在>=24.0.0支持库中解决,但如果出于某种原因,您仍然必须使用旧版本,这里有一个解决方法
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull final View bottomSheet, int newState) {
bottomSheet.post(new Runnable() {
@Override
public void run() {
//workaround for the bottomsheet bug
bottomSheet.requestLayout();
bottomSheet.invalidate();
}
});
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
我也遇到了同样的问题,当我试图根据内容更新偷窥高度时,发现了以前布局的高度。这是有道理的,因为新的布局还没有发生。通过在UI线程上发布,在新布局之后计算布局高度,并发出另一个布局请求以将底部图纸更新到正确的高度
void show() {
setVisibility(View.VISIBLE);
post(new Runnable() {
@Override
public void run() {
mBottomSheetBehavior.setPeekHeight(findViewById(R.id.sheetPeek).getHeight());
requestLayout();
}
})
}
我遵循了@Haraldunader的建议,它给了我一个实际有效的想法。如果在BottomSheetBehavior.state
被编程设置为state\u COLLAPSED
之后运行线程(无法使其与post方法一起工作),则您已经可以获得视图的高度,并根据其内容设置peekeheight
因此,首先要设置BottomSheetBehavior
:
BottomSheetBehavior.from(routeCaptionBottomSheet).state = BottomSheetBehavior.STATE_COLLAPSED
然后动态设置“偷看高度”:
thread {
activity?.runOnUiThread {
val dynamicHeight = yourContainerView.height
BottomSheetBehavior.from(bottomSheetView).peekHeight = dynamicHeight
}
}
如果使用Java(我将Kotlin与Anko一起用于线程),这可以做到:
new Thread(new Runnable() {
public void run() {
int dynamicHeight = yourContainerView.getHeight();
BottomSheetBehavior.from(bottomSheetView).setPeekHeight(dynamicHeight);
}
}).start();
对于底部工作表对话框片段,请阅读以下内容:
@覆盖
ActivityCreated上的公共无效(@Nullable Bundle savedinStateCState){
super.onActivityCreated(savedInstanceState);
BottomSheetDialog=(BottomSheetDialog)getDialog();
FrameLayout bottomSheet=dialog.findviewbyd(com.google.android.material.R.id.design\u bottom\u sheet);
BottomSheetBehavior=BottomSheetBehavior.from(bottomSheet);
behavior.setState(behavior.STATE_扩展);
行为。设置高度(0);
}
下面的代码片段帮助我解决了这个问题,我在布局中不同视图的可见性和底部图纸的高度之间切换
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.your_bottom_sheet_layout, container, false)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
dialog.setContentView(R.layout.your_bottom_sheet_layout)
dialog.setOnShowListener {
val castDialog = it as BottomSheetDialog
val bottomSheet = castDialog.findViewById<View?>(R.id.design_bottom_sheet)
val behavior = BottomSheetBehavior.from(bottomSheet)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
behavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
}
return dialog
}
override fun onCreateView(充气机:布局充气机,容器:ViewGroup?,savedInstanceState:Bundle?):视图?{
返回充气机。充气(右布局。您的底部图纸布局,容器,假)
}
重写FunonCreateDialog(savedInstanceState:Bundle?:对话框){
val dialog=super.onCreateDialog(savedInstanceState)作为BottomSheetDialog
对话框.setContentView(R.layout.your\u bottom\u sheet\u布局)
dialog.setOnShowListener{
val castDialog=它作为BottomSheetDialog
val bottomSheet=castDialog.findViewById(R.id.design\u bottom\u sheet)
val behavior=BottomSheetBehavior.from(bottomSheet)
behavior.state=BottomSheetBehavior.state\u已展开
setBottomSheetCallback(对象:BottomSheetBehavior.BottomSheetCallback()){
覆盖状态更改(底部工作表:视图,新闻状态:Int){
if(newState==BottomSheetBehavior.STATE\u拖动){
behavior.state=BottomSheetBehavior.state\u已展开
}
}
覆盖滑轨上的乐趣(底页:视图,滑轨偏移:浮动){}
})
}
返回对话框
}
我一直在努力解决一个与你类似的问题
手动设置底部板材的高度是我的解决方案
具有具有BottomSheetBehavior的视图视图a和修改视图高度的自定义方法modifyHeight():
viewA?.modifyHeight()
viewA?.measure(
MeasureSpec.makeMeasureSpec(
width,
MeasureSpec.EXACTLY
),
MeasureSpec.makeMeasureSpec(
0,
MeasureSpec.UNSPECIFIED
)
)
val layoutParams = LayoutParams(viewA.measuredWidth, viewA.measuredHeight)
val bottomSheet = BottomSheetBehavior.from(viewA)
layoutParams.behavior = bottomSheet
viewA.layoutParams = layoutParams
我的布局类似于:
<com.yourpackage.ViewA
android:id="@+id/viewA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_peekHeight="50dp"
app:layout_behavior="@string/bottom_sheet_behavior" />
重用旧layoutParams的BottomSheetBehavior非常重要,因为它包含您可能附加的peekHeight和侦听器
这里是切换按钮点击监听器,我用它来设置底部板材的拾取高度
FrameLayout standardBottomSheet=findViewById(R.id.standardBottomSheet);
BottomSheetBehavior BottomSheetBehavior=BottomSheetBehavior.from(standardBottomSheet);
btnToggleBottomSheet.setOnClickListener(新的HPFM_OnSingleClickListener(){
@凌驾
单个单击上的公共无效(视图v){
if(bottomSheetBehavior.getPeekHeight()==0){
ObjectAnimator.ofInt(bottomSheetBehavior,“peekHeight”,200).setDuration(300).start();
}
否则{
ObjectAnimator.ofInt(bottomSheetBehavior,“peekHeight”,0).setDuration(300).start();
}
}
});
您可以将视图高度设置为包裹父视图,然后在加载内容后使视图无效view heig
<com.yourpackage.ViewA
android:id="@+id/viewA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_peekHeight="50dp"
app:layout_behavior="@string/bottom_sheet_behavior" />
FrameLayout standardBottomSheet = findViewById(R.id.standardBottomSheet);
BottomSheetBehavior<FrameLayout> bottomSheetBehavior = BottomSheetBehavior.from(standardBottomSheet);
btnToggleBottomSheet.setOnClickListener(new HPFM_OnSingleClickListener() {
@Override
public void onSingleClick(View v) {
if (bottomSheetBehavior.getPeekHeight() == 0) {
ObjectAnimator.ofInt(bottomSheetBehavior, "peekHeight", 200).setDuration(300).start();
}
else {
ObjectAnimator.ofInt(bottomSheetBehavior, "peekHeight", 0).setDuration(300).start();
}
}
});