web-dev-qa-db-ja.com

Androidサポートライブラリ23.2.1でBottomSheetの動作を理解してみてください

自分のアクティビティの1つにボトムシートを実装しようとしていますが、その動作に少し混乱しています。

だからここに問題があります、私はボトムシートを見せようとしている活動があります、そして私はそれを見ます:

  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);
}
8
sujay

この問題にさらに数日間取り組んだ後、私はこれに対する1つの代替ソリューションを見つけました:

レイアウト内で直接Bottom_sheetを使用する代わりに、Bottom_Sheetフラグメントを作成してアクティビティでインスタンス化すると、この問題は発生せず、下部シートが非表示になり、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());

これにより、アクティビティの開始時にボトムシートが非表示にならないという私の問題は実際に解決されましたが、bottom_sheetが直接含まれていると、なぜその問題に直面するのか理解できません。

4
sujay

(質問を参照)Suzziは、コードの問題として、onCreate内でsetStateメソッドを直接呼び出そうとしていることを示しています。 WeakReferenceがまだ初期化されていないため、これはnullPointerをスローします。コーディネーターレイアウトが子ビューを配置しようとすると、初期化されます。

onLayoutChild(CoordinatorLayout親、V子、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に設定されます。

このデモアプリを作成するために私が従ったチュートリアルを以下に示します。 ボトムシートAndroidデザインサポートライブラリ

2
Rohit Ramkumar

クラッシュする理由は、onLayoutChildの最後の行の1つまで弱参照が設定されていないためです。これにより、nullptr例外が発生します。

できることは、カスタムBottomSheetビヘイビアーを作成し、onLayoutChildをオーバーライドして、そこで展開状態を設定することです。

例はここにあります: AppCompat BottomSheetsを使用したNullPointerExeption

1
12vi6

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);
            }
        });
1
iam thadiyan