Hömafreak
Hömafreak

Reputation: 57

Drawer Navigation, it's fragments buttons doesn't find the right actionlistener

I've some problems with the drawer navigation. I've tried much and googled a lot but didn't find a solution. I'm using a drawer navigation. There you have to fill it's frame layout with fragments. That works fine, so for example: I pick something in the drawer navigation and it's frame layout loads the fragment (startdisplay in my app) with buttons and textviews. Now I click on one of the fragments buttons, this should call the actionlistener in the fragments java class (startdisplay.java), but instead it's not finding these actionlisteners (android studio also tells me that these are never used). I found out that the app is looking in the drawer navigation class (mainmenuactivity in my app).

My question is if there is a way that my app is looking directly in the fragments java class, because I can't put all my code in one class (mainmenuactivity). Of course this won't be my only fragment that I'd have to put in there.

Here is the code: The XML of the Startdisplay Fragment:

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="de.touristenfahrerforum.MarcelMoiser.Fragments.Startdisplay">

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <Button
        android:id="@+id/startButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="114dp"
        android:onClick="startButton"
        android:text="Start"
        android:textSize="50sp" />
....

The java class of the Startdisplay fragment:

public class Startdisplay extends Fragment
{
....
private Activity activity;

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

    loadTrackText   = (TextView)view.findViewById(R.id.loadTrackText);
    loadModeText    = (TextView)view.findViewById(R.id.loadModeText);
    loadBestlapText = (TextView)view.findViewById(R.id.loadBestlapText);

    fileService = new Fileservice();

    activity = this.getActivity();

    return view;
}
....
/**
 * Actionlistener für den Start Button
 */
public void startButton(View view)    //!!!!!!!!!!!!!!This method should be called when the button is pressed <-------------------------------------------------------------
{
    if(track != null)
    {
        if( ((LocationManager) activity.getSystemService(activity.LOCATION_SERVICE)).isProviderEnabled(LocationManager.GPS_PROVIDER))
        {//GPS ist aktiviert
            Intent intent = new Intent(activity, MainActivity.class);

            intent.putExtra(V.TRACK_EXTRA, track);  //Hier könnte man vll auch nur den String statt dem Objekt übergeben <------
            intent.putExtra(V.MODE_EXTRA, mode);
            intent.putExtra(V.BESTLAP_EXTRA, bestlap);

            startActivity(intent);
        }
        else{}//Meldung geben das das GPS nicht aktiviert ist
    }
    else{}//else es muss erst eine Strecke geladen werden
}
....

The Mainmenu XML (Drawer Layout):

    <?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_menu"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111" />

</android.support.v4.widget.DrawerLayout>

And the Mainmenuactivity(where the app searches for the startButton actionlistener):

public class MainMenuActivity extends Activity
{
    private String[] menuItems;
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;

    private CharSequence mTitle;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_menu);

        //Standartwerte für die Einstellungen erzeugen
        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);

        mTitle = getTitle();
        menuItems = new String[]{"Peter","Susi","Elephant"};
        mDrawerLayout = (DrawerLayout) findViewById(R.id.main_menu);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        //Holt sich den Wert für die Umrechnung zwischen PX und DP
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        V.LOGICAL_DENSITY = metrics.density;

        // Set the adapter for the list view
        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_list_item, menuItems));
        // Set the list's click listener
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
    }

    /* The click listner for ListView in the navigation drawer */
    private class DrawerItemClickListener implements ListView.OnItemClickListener
    {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id)
        {
            selectItem(position);
        }
    }

    /** Swaps fragments in the main content view */
    private void selectItem(int position)
    {
        // Create a new fragment and specify the planet to show based on position


        // Insert the fragment by replacing any existing fragment
        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.content_frame, new Startdisplay())
        .commit();

        // Highlight the selected item, update the title, and close the drawer
        mDrawerList.setItemChecked(position, true);
        setTitle(menuItems[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
    }

    @Override
    public void setTitle(CharSequence title)
    {
        mTitle = title;
        getActionBar().setTitle(mTitle);
    }
}

I'm only testing, so the menuItems have no sense and it's always loading the Startdisplay fragment, whatever I click on. So like I already said, the app should use the actionlistener in the Startdisplay.java and should not search for it in the MainMenuActivity.java. Thanks in advance

Upvotes: 1

Views: 506

Answers (1)

Malcolm
Malcolm

Reputation: 41510

Your problem is that when you set the attribute android:onClick, the method is looked for in the context of this view. The context of the view is, of course, the activity and not the fragment, which is why Android can't find your method there. So you have two options:

  1. Put the method into the activity and delegate to the fragment.
  2. Use View.OnClickListener instead.

In general I personally don't really like using android:onClick anyway because it is very easy to break. If it doesn't work, it just silently fails, like in your case. Therefore, I would use the second way.

Call something like this in onCreateView() of the fragment:

view.findViewById(R.id.startButton).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //Do what you need
    }
});

Upvotes: 1

Related Questions