2

I have a custom BottomSheetDialogFragment and I want to set its TextView from my MainActivity. I've tried to get a reference to its view but I got a null pointer exception. I create the Fragment from my MainActivity like this:

public void buttonClick(View view) {
    CustomBottomSheetDialogFragment bottomSheetDialogFragment = new CustomBottomSheetDialogFragment();
    View sheetView = bottomSheetDialogFragment.getView();
    TextView sheetText = (TextView) sheetView.findViewById(R.id.cmp1); 
    sheetText.setText("blah");
    bottomSheetDialogFragment.show(getSupportFragmentManager(), "Dialog");
}

Here is my BottomSheetDialogFragment class:

public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.content_bottom_sheet, container, false);
        return v;
    }
}

And here's the XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:id="@+id/bottomSheetLayout"
   android:layout_width="match_parent"
   android:layout_height="300dp"
   android:background="@android:color/white"
   android:padding="16dp"
   app:behavior_hideable="true"
   app:behavior_peekHeight="60dp"
   app:layout_behavior="@string/bottom_sheet_behavior">

   <TextView
       android:id="@+id/bottomSheetHeading"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="Test"
       android:textAppearance="@android:style/TextAppearance.Large" />

   <TextView
       android:id="@+id/cmp1"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_below="@id/bottomSheetHeading"
       android:layout_centerHorizontal="true"
       android:layout_marginTop="16dp"
       android:text="Test Message"
       android:textAppearance="@android:style/TextAppearance.Medium" />

</RelativeLayout>

How do I correctly get a reference to the textview? Thanks!

Edit: Here's the error:

java.lang.IllegalStateException: Could not execute method for android:onClick
                                                                                 at android.view.View$DeclaredOnClickListener.onClick(View.java:4725)
                                                                                 at android.view.View.performClick(View.java:5637)
                                                                                 at android.view.View$PerformClick.run(View.java:22429)
                                                                                 at android.os.Handler.handleCallback(Handler.java:751)
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                 at android.os.Looper.loop(Looper.java:154)
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                                                                              Caused by: java.lang.reflect.InvocationTargetException
                                                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                                                 at android.view.View$DeclaredOnClickListener.onClick(View.java:4720)
                                                                                 at android.view.View.performClick(View.java:5637) 
                                                                                 at android.view.View$PerformClick.run(View.java:22429) 
                                                                                 at android.os.Handler.handleCallback(Handler.java:751) 
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                                 at android.os.Looper.loop(Looper.java:154) 
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:6119) 
                                                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
                                                                              Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
                                                                                 at com.gofrontrow.conductor_mobile.MainActivity.buttonClick(MainActivity.java:108)
                                                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                                                 at android.view.View$DeclaredOnClickListener.onClick(View.java:4720) 
                                                                                 at android.view.View.performClick(View.java:5637) 
                                                                                 at android.view.View$PerformClick.run(View.java:22429) 
                                                                                 at android.os.Handler.handleCallback(Handler.java:751) 
                                                                                 at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                                 at android.os.Looper.loop(Looper.java:154) 
                                                                                 at android.app.ActivityThread.main(ActivityThread.java:6119) 
                                                                                 at java.lang.reflect.Method.invoke(Native Method) 
                                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 

Final Edit: In the end, I just made a constructor for the fragment and passed the string that way. I used this post as a guide.

Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
Jason
  • 445
  • 1
  • 6
  • 16

1 Answers1

2

I propose a different approach, simply create a method inside of your BottomSheetDialogFragment called buttonClick or whatever really. And inside of onCreateView bind the TextView to it's id like so:

View v = inflater.inflate(R.layout.content_bottom_sheet, container, false);
// declare it as a field at the top of the class
sheetText = (TextView) v.findViewById(R.id.cmp1);
return v;

And now that you have a reference to your sheetText TextView, you can create a normal method like so:

void onButtonClick(String text){
    sheetText.setText(text);
}

And you can call this one from MainActivity like so:

public void buttonClick(View view) {
    CustomBottomSheetDialogFragment bottomSheetDialogFragment = new CustomBottomSheetDialogFragment();
    bottomSheetDialogFragment.show(getSupportFragmentManager(), "Dialog");
    bottomSheetDialogFragment.onButtonClick("whatever);
}

Also, if you dont want to continually change the text on button click in MainActivity, you can also pass the parameter to the constructor, if I misunderstood what you're trying to do.

Kirguduck
  • 748
  • 1
  • 9
  • 20
Vucko
  • 7,371
  • 2
  • 27
  • 45
  • Thanks, I just tried this and I still got "Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference" – Jason Jul 14 '17 at 16:57
  • I know that when I just want to "show" the bottomsheet, it works. It's accessing the textview that is crashing for some reason. – Jason Jul 14 '17 at 17:00
  • OK I added print statements in onButtonClick and onCreateView, what's happening is that the "onButtonClick" method is called before onCreateView is. I have no idea why, even when the onButtonClick is below .show in the mainactivity. What is going on here? – Jason Jul 14 '17 at 21:05
  • 1
    The reason is it takes some time for the fragment to be created. Try the 2nd solution I provided, pass the parameter to the constructor of your DialogFragment, and save it as a field, then in onCreateView set the text of the textView to that value. Ok? – Vucko Jul 15 '17 at 11:08
  • that worked! I did have to look up how to avoid using non-default constructors for fragments but your second solution worked! – Jason Jul 17 '17 at 15:20