How do I "findViewById" with fragments?

Yusuf picture Yusuf · Aug 10, 2015 · Viewed 25.9k times · Source

I recently moved my project to Android Studio from Eclipse. I am trying to get the email functionality working, however I receive errors by "findViewById". I also receive errors by "Toast.makeText". Could you please assist on both errors. The code in my class is as follows:

package com.example.ishonours.witsbusapp;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import android.content.Intent;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class ComplaintsFragment extends Fragment {

//I added
private EditText recipient;
private EditText subject;
private EditText body;


private OnFragmentInteractionListener mListener;
private static final String ARG_SECTION_NUMBER = "5";

public static ComplaintsFragment newInstance(int menuNumber) {
    ComplaintsFragment fragment = new ComplaintsFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_SECTION_NUMBER, menuNumber);
    fragment.setArguments(args);
    return fragment;
}

public ComplaintsFragment() {
    // Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return  inflater.inflate(R.layout.fragment_complaints, container, false);

    //i added
    recipient = (EditText) findViewById(R.id.recipient);
    subject = (EditText) findViewById(R.id.subject);
    body = (EditText) findViewById(R.id.body);
    Button sendBtn = (Button) findViewById(R.id.sendEmail);
    sendBtn.setOnClickListener(new View.OnClickListener() {

        public void onClick(View view) {
            sendEmail();
            // after sending the email, clear the fields
            recipient.setText("");
            subject.setText("");
            body.setText("");
        }
    });


}

//i added
protected void sendEmail() {
    String[] recipients = {recipient.getText().toString()};
    Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
    // prompts email clients only
    email.setType("message/rfc822");
    email.putExtra(Intent.EXTRA_EMAIL, recipients);
    email.putExtra(Intent.EXTRA_SUBJECT, subject.getText().toString());
    email.putExtra(Intent.EXTRA_TEXT, body.getText().toString());
    try {
        // the user can choose the email client
        startActivity(Intent.createChooser(email, "Choose an email client from..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(ComplaintsFragment.this, "No email client installed.",
               Toast.LENGTH_LONG).show();
    }}




public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    ((MainActivity) activity).onSectionAttached(
            getArguments().getInt(ARG_SECTION_NUMBER));
}


@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    public void onFragmentInteraction(Uri uri);
}

}

The code in my xml file is:

<LinearLayout 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"
    android:orientation="vertical" >
    tools:context="com.example.ishonours.witsbusapp.ComplaintsFragment">

<TextView
    android:id="@+id/text1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="20dp"
    android:gravity="center"
    android:text="Complete the fields to log a complaint"
    android:textAppearance="?android:attr/textAppearanceMedium" />

<EditText
    android:id="@+id/recipient"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ems="10"
    android:inputType="textEmailAddress"
    android:hint="Recipient" />
<EditText
    android:id="@+id/subject"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ems="10"
    android:hint="Subject" />
<EditText
    android:id="@+id/body"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ems="10"
    android:hint="Message body" />
<Button
    android:id="@+id/sendEmail"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="30dp"
    android:text="Compose an email" />

Answer

pelotasplus picture pelotasplus · Aug 10, 2015

The problem is in your onCreateView method.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
     // Inflate the layout for this fragment
     View v = inflater.inflate(R.layout.fragment_complaints, container, false);

     //i added
     recipient = (EditText) v.findViewById(R.id.recipient);

     [...]

     return v;
}

See the difference? You have to call findViewById on actual View object in case of Fragments.

And the problem with Toast you have is because you are passing worng object as first parameter. You need Context and you are passing Fragment. Fragment is not a Context but luckly for you Activity is so, you have to construct your Toast like this:

Toast.makeText(ComplaintsFragment.this.getActivity(), "No email client installed.",
           Toast.LENGTH_LONG).show();

Note that getActivity() call.