0

I am trying to make a simple toggle button that simply displays text. However, when I press the button my app crashes with the error message "app has Stopped". I theorize this has something to do with fragments and activities not linking correctly. Here is the xml for the page with the button:

<ToggleButton
    android:text="ToggleButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="62dp"
    android:id="@+id/toggleButton"
    android:textOn="Night Mode"
    android:textOff="Day Mode"
    android:layout_below="@+id/textView4"
    android:layout_toLeftOf="@+id/textView4"
    android:layout_toStartOf="@+id/textView4"
    android:layout_marginRight="8dp"
    android:layout_marginEnd="8dp"
    android:onClick="changeTheme"/>

And in MainActivity.java, I defined the function:

public void changeTheme(View view){
    boolean checked = ((ToggleButton)view).isChecked();

    if(checked)
    {
        textView.setText("On");
        textView.setVisibility(View.VISIBLE);
    }
    else
    {
        textView.setText("Off");
        textView.setVisibility(View.VISIBLE);
    }

}

Referencing a TextView initialized here:

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {

//this text view
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //initialized the text view here
    textView = (TextView)findViewById(R.id.themeBtnText);

    //initialize view to my events
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.content_frame, new EventsFragment())
            .commit();

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);
}

Does anyone have any idea why pressing this button causes the app to crash? Will post more info if needed.

Edit: Here is the full error message from Android Studio

     --------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.thememeteam.eventspoll, PID: 2300
                  java.lang.IllegalStateException: Could not execute method for android:onClick
                      at android.view.View$DeclaredOnClickListener.onClick(View.java:4452)
                      at android.view.View.performClick(View.java:5198)
                      at android.widget.CompoundButton.performClick(CompoundButton.java:122)
                      at android.view.View$PerformClick.run(View.java:21147)
                      at android.os.Handler.handleCallback(Handler.java:739)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:148)
                      at android.app.ActivityThread.main(ActivityThread.java:5417)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                   Caused by: java.lang.reflect.InvocationTargetException
                      at java.lang.reflect.Method.invoke(Native Method)
                      at android.view.View$DeclaredOnClickListener.onClick(View.java:4447)
                      at android.view.View.performClick(View.java:5198) 
                      at android.widget.CompoundButton.performClick(CompoundButton.java:122) 
                      at android.view.View$PerformClick.run(View.java:21147) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:148) 
                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
                   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
                      at com.thememeteam.eventspoll.MainActivity.changeTheme(MainActivity.java:111)
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at android.view.View$DeclaredOnClickListener.onClick(View.java:4447) 
                      at android.view.View.performClick(View.java:5198) 
                      at android.widget.CompoundButton.performClick(CompoundButton.java:122) 
                      at android.view.View$PerformClick.run(View.java:21147) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:148) 
                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

1 Answers1

0

Edited answer which has it working:

You needed to move your objects logic into the fragment class.

In your MainActivity, you need to remove this method which I have commented out:

//     public void changeTheme(View view){
//        boolean checked = ((ToggleButton)view).isChecked();
//
//        if(checked)
//        {
//            textView.setText("On");
//            textView.setVisibility(View.VISIBLE);
//        }
//        else
//        {
//            textView.setText("Off");
//            textView.setVisibility(View.INVISIBLE);
//        }
//
//    }

Then in your SettingsFragment, I referenced and initialized your TextView and ToggleButton. Added an onClickListener to the ToggleButton to handle the click instead of doing it through the XML, and then fixed the boolean check on the ToggleButton.

public class SettingsFragment extends Fragment {

View myView;

//added
ToggleButton toggleButton;
TextView textView;


@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    myView = inflater.inflate(R.layout.settings, container, false);

    //added
    textView = (TextView) myView.findViewById(R.id.themeBtnText);
    toggleButton = (ToggleButton) myView.findViewById(R.id.toggleButton);



    toggleButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            changeTheme(myView);
        }
    });







    return myView;
}

public void changeTheme(View view){
    boolean checked = (toggleButton.isChecked());

    if(checked)
    {
        textView.setText("On");
        textView.setVisibility(View.VISIBLE);
    }
    else
    {
        textView.setText("Off");
        textView.setVisibility(View.INVISIBLE);
    }

}

}

Nick Friskel
  • 2,369
  • 2
  • 20
  • 33
  • It looks like your textView is not referenced, can you please post your full MainActivity code and I should be able to fix it for you. – Nick Friskel Dec 09 '16 at 02:01
  • Hmm didn't change it. That textView throws the warning that it is never being used, as it is different than the one in MainActivity. Because the button's function is in MainActivity right? – Huzefa Mandviwala Dec 09 '16 at 02:13
  • If you want to upload the project to github so I can get all the files I can figure it out. I remember having the same problem when dealing with fragments and I was able to figure it out by moving around where the views are initialized – Nick Friskel Dec 09 '16 at 02:19
  • https://github.com/HuzefaMandvi/ihateandroidstudio/ – Huzefa Mandviwala Dec 09 '16 at 02:46
  • Alright my dude, I edited my answer to a working version. Just remove that method in MainActivity and you can get rid of the view references for the TextView and ToggleButton too. Then check out the SettingsActivity, working on my end :) – Nick Friskel Dec 09 '16 at 03:15
  • Thank you so much! I'm new to Android programming and this was insanely helpful. So the fragment should generally act as the activity file for the XML that it corresponds to? – Huzefa Mandviwala Dec 09 '16 at 03:20
  • No problem :) yeah pretty much, it's just like a mini activity of its own with its parent activity view passed through. Glad I could help! – Nick Friskel Dec 09 '16 at 03:23