【问题标题】:Try to Understand the behavior of BottomSheet in android support library 23.2.1尝试了解 android 支持库 23.2.1 中 BottomSheet 的行为
【发布时间】:2016-03-20 05:54:05
【问题描述】:

我正在尝试在我的一项活动中实施底部工作表,但我对它的行为方式感到有点困惑!

所以这是问题所在,我有一个活动,我试图显示底部表,我看到了:

  1. 如果我们不设置app:behavior_peekHeight 属性,那么底部表格将永远无法工作

  2. 如果您将 PeekHeight 设置为小于 30dp(基本上只是为了将其从屏幕上隐藏)

  3. 如果您在布局文件中将 app:behavior_peekHeight 设置为超过 30dp,并尝试在您的 onCreate 方法中将 bottomSheetBehavior 的状态设置为 STATE_HIDDEN,您的应用会因此错误而崩溃

原因:

java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.Object java.lang.ref.WeakReference.get()' on a null object reference             at    android.support.design.widget.BottomSheetBehavior.setState(BottomSheetBehavior.jav    a:440)
at myapp.activity.SomeActivity.onCreate(SomeActivity.java:75)

我真的很困惑为什么不允许我将它隐藏在 onCreate 中?或者为什么我们不能将 peekHeight 设置为 0 以便它在屏幕上不可见,除非我们调用 STATE_EXPANDED 或者甚至不设置该属性应该默认隐藏!或者至少我应该能够在我的 onCreate 中将其设置为隐藏!

我错过了什么吗?还是 BottomSheet 的行为是刚性的?

我的 BottomSheet 布局文件是这样的:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:background="@android:color/white"
android:layout_height="100dp"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="40dp" <!-- I cant set this less than 30dp just to hide-->
app:layout_behavior="@string/bottom_sheet_behavior"
tools:context="someActivity"
android:id="@+id/addressbottomSheet"
tools:showIn="@layout/some_activity">

在我的活动中,我正在做这样的事情:

@InjectView(R.id.addressbottomSheet)
 View bottomSheetView;
@Override
protected void onCreate(Bundle savedInstanceState) {
....
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetView);

// only if I have set peek_height to more than 30dp
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); 
}

在我的 onclick 中,我正在这样做:

@Override
public void onItemClick(View view, int position) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}

【问题讨论】:

  • 您是否找出第一种情况的原因:如果我们不设置 app:behavior_peekHeight 属性,那么底部工作表将永远无法工作?我也一样。
  • @LạngHoàng 这个答案可能会帮助你stackoverflow.com/a/36236743/3000299

标签: android android-support-library bottom-sheet


【解决方案1】:

在解决这个问题几天后,我找到了一个替代解决方案:

而不是直接在布局中使用 Bottom_sheet,如果我们创建一个 Bottom_Sheet 片段然后在 Activity 中实例化它,则不会发生此问题,底部工作表将被隐藏,我们不需要指定 peek_height

这就是我所做的

public class BottomSheetDialog extends BottomSheetDialogFragment implements View.OnClickListener {
    @Override
    public View onCreateView(LayoutInflater inflater, 
                             ViewGroup container, 
                             Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_bottom_sheet, container, false);
}

然后在我的活动中

bottomSheetDialog = BottomSheetDialog.newInstance(addressList.get(position), position);
bottomSheetDialog.show(getSupportFragmentManager(), AddressActivity.class.getSimpleName());

这实际上解决了我在活动开始时底部工作表没有隐藏的问题,但我仍然无法理解为什么如果直接包含底部工作表我们会遇到这个问题!

【讨论】:

  • 执行此操作会将您的工作表从持久底片更改为模型底片。尽管这似乎并不重要,但它可能会产生巨大的影响。例如,持久底页允许与其上方的内容进行交互(滑动、打字等)。而模型底板则没有。
【解决方案2】:

(参考问题)Suzzi 兄弟,您的代码问题是您试图直接在 onCreate 中调用 setState 方法。这将抛出一个 nullPointer,因为 WeakReference 尚未初始化。当 Coordinator 布局即将放置其子视图时,它将被初始化。

onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection)

当父 CoordinatorLayout 是关于布局的时候调用 给定子视图。

所以最好的方法是将窥视高度设置为 0 并在 onItemClick 侦听器中显示/隐藏。 这是我的代码:

bottom_sheet.xml

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:gravity="center"
    android:orientation="vertical">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Bottom sheet"
        android:textColor="@android:color/black" />

</LinearLayout>

activity_main.xml

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Show hide bottom sheet" />


<include
    android:id="@+id/gmail_bottom_sheet"
    layout="@layout/bottom_sheet" />

MainActivity.java

 public class MainActivity extends AppCompatActivity {
        boolean isExpanded;
        Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CoordinatorLayout coordinatorLayout = (CoordinatorLayout) findViewById(R.id.gmail_coordinator);
        final View bottomSheet = coordinatorLayout.findViewById(R.id.gmail_bottom_sheet);
        final BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (isExpanded) {
                    behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                } else {
                    behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                }
                isExpanded = !isExpanded;
            }
        });

    }
    }

这里最初是不可见的底部工作表。单击按钮后,我们将状态设置为 STATE_COLLAPSED/STATE_EXPANDED。

下面列出了我制作此演示应用程序所遵循的教程: Bottom Sheet with Android Design Support Library

【讨论】:

  • 是的,我尝试了这种方法,但使用这种方法,我遇到的问题是我必须将底部工作表中的 peek_height 属性设置为超过 30 我有点困惑,因为如果我将它设置为零什么都没有工作!没有错误,也没有底页我不知道为什么会这样!但是在三件事中,您的回答帮助我找出了其中一件与“弱参考”有关的原因!谢谢你的回答
【解决方案3】:

它崩溃的原因是弱引用直到 onLayoutChild 中的最后一行才被设置,这给了你空 ptr 异常。

你可以做的是创建一个自定义的 BottomSheet Behavior 并覆盖 onLayoutChild,在那里设置展开状态。

可以在此处找到示例: NullPointerExeption with AppCompat BottomSheets

【讨论】:

  • 建议使用自定义活动并继承它可以解决问题,但为什么没有首先设置弱引用?在子布局未完全加载之前不设置weakReference是否重要?
【解决方案4】:

为避免 Null 指针异常,在 onCreate() 中像这样将状态设置为 HIDDEN

View bottomSheetView = findViewById(R.id.bottomsheet_review_detail_id);
mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheetView);
bottomSheetView.post(new Runnable() {
            @Override
            public void run() {
                mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
            }
        });

【讨论】:

  • 这个解决方案有效,但是在涉及到 Activity 的生命周期时存在问题......例如,如果在 Activity 暂停后执行 runnable。
  • 我如何获得状态,就像我想看到的是全视图显示或用户需要向上滚动。这样如果存在更多数据然后是当前视图,我可以在底部显示更多信息按钮
  • 我如何获得状态,就像我想看到的是全视图显示或用户需要向上滚动。这样如果存在更多数据然后是当前视图,我可以在底部显示更多信息按钮
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 2016-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多