4

I am using fragments,I have an edittext in fragment and I want to get value in main activity.

This is my fragment layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#878787" >

        <TextView android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="dfgdfgdf"
        android:textSize="20dp"
        android:layout_centerInParent="true"
        android:id="@+id/user_name"/>

    <EditText
    android:id="@+id/message"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
   />

    <Button 
        android:text="Gönder"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="getFromUser"
        android:layout_marginTop="40dp"
        />

</RelativeLayout>

I am loading fragment with this function:

public void startChat(JsonObject user) {
    FrameLayout layout = (FrameLayout)findViewById(R.id.container);
    layout.setVisibility(View.VISIBLE); 
    Bundle bundle = new Bundle();
    bundle.putString("name", user.get("name").getAsString());
    sendTo=user.get("username").getAsString();
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    ConversationFragment conv = new ConversationFragment();
    conv.setArguments(bundle);
    fragmentTransaction.add(R.id.container, conv);
    fragmentTransaction.commit();
    viewPager.setVisibility(View.GONE);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    actionBar.setDisplayHomeAsUpEnabled(true);

}

And this is my fragment class

public class ConversationFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        String name = getArguments().getString("name");
        View rootView = inflater.inflate(R.layout.fragment_conversation, container, false);
        TextView username=(TextView)rootView.findViewById(R.id.user_name);
        username.setText(name);
        return rootView;
    }
}

As you can see when press the button main activity runs "getFromUser" function.I want to get edittext value in this function.How can I do this ?

Tolgay Toklar
  • 4,151
  • 8
  • 43
  • 73

2 Answers2

4

It's always the same procedure for these things. You can't access a fragment's views just like that. You need a callback method.

Add this code to ConversationFragment:

private OnGetFromUserClickListener mListener;

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnGetFromUserClickListener ) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement OnGetFromUserClickListener");
    }
}

public void getFromUser(View v) {
    if (mListener != null) {
        EditText edit = (EditText)findViewById(R.id.message);
        mListener.getFromUser(edit.getText().toString());
    }
}

public interface OnGetFromUserClickListener {
    void getFromUser(String message);
}

Make your MainActivity implement this interface. Replace getFromUser() inside MainActivity with:

public void getFromUser(String message) {
    sendMessage(message);
}

Done.

Edit: Actually, using the XML-onClick attribute is currently bugged (see onClick inside fragment called on Activity): It links to the activity instead of the fragment. You have to set the click listener programmatically to make sure the code won't break at some point in the future. So give the button an ID inside the XML (e.g. get_from_user) and add this code to onCreateView inside ConversationFragment:

v.findViewById(R.id.get_from_user).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.get_from_user) {
            getFromUser(v);
        }
    }
});

Using this code vastly decouples the activity and the fragment from each other.

Community
  • 1
  • 1
0101100101
  • 5,786
  • 6
  • 31
  • 55
  • As I said, make your activity implement OnGetFromUserClickListener. – 0101100101 Aug 05 '14 at 13:18
  • I don't understand how can I implete this code in main activity.Can you look at this ? http://pastebin.com/WQHgeCdZ – Tolgay Toklar Aug 05 '14 at 14:46
  • Just do everything above one by one? Don't forget to add ", ConversationFragment.OnGetFromUserClickListener" behind "implements ActionBar.TabListener". – 0101100101 Aug 05 '14 at 15:04
  • I did like this: main activity:http://pastebin.com/BuZeK5je this is fragment:http://pastebin.com/0jaMrPw1 but I app is crashing this is the error log:http://prntscr.com/49syle – Tolgay Toklar Aug 05 '14 at 15:26
  • I saw your comment but I don't know how can I implement the listener.Can you give an example ? – Tolgay Toklar Aug 06 '14 at 08:04
  • public class MainActivity extends FragmentActivity implements ActionBar.TabListener, ConversationFragment.OnGetFromUserClickListener { ... } – 0101100101 Aug 06 '14 at 08:25
  • Thank you so much,it's working now.I have one more question,how can I run a fragment function from main activity ? – Tolgay Toklar Aug 06 '14 at 09:20
  • Edit:http://stackoverflow.com/questions/12659747/call-an-activity-method-from-a-fragment I did like this.What do you think about ? Is valid ? – Tolgay Toklar Aug 06 '14 at 09:34
  • 1
    Doing it like you already are (using setArguments and getArguments) is best practice. In those cases where you really have to update a fragment when it's already shown, you could call getSupportFragmentManager().findFragmentById(...) or save your fragment in a variable. There's enough information about this here on Stack Overflow. – 0101100101 Aug 06 '14 at 10:01
2

I resolved this problem.

public void getFromUser(View view) {        
    ConversationFragment fragment1 = (ConversationFragment)getSupportFragmentManager().findFragmentById(R.id.container);
    View frag=fragment1.getView();
    EditText editText1 =(EditText) frag.findViewById(R.id.message);
    String message=editText1.getText().toString();
    sendMessage(message);
}

Now I can get edittext value from fragment.

Tolgay Toklar
  • 4,151
  • 8
  • 43
  • 73
  • -1. According to [onClick inside fragment called on Activity](http://stackoverflow.com/a/7808223/2964379) onClick is not meant to work this way. It's bad practice and thus not a solution to your issue. My code actually doesn't work because of the bug, which makes sure the fragment's getFromUser is never called. Using mine after I fix it will make sure your code still works in the future. – 0101100101 Aug 05 '14 at 13:41
  • But it's working,you mean this code will not work in the future ? – Tolgay Toklar Aug 05 '14 at 13:48
  • Not sure, but it might happen. In any case, the code you provided works, but it's not clean code (see [this answer and its comments to How to handle button clicks using the xml onClick within Fragments](http://stackoverflow.com/a/6271637/2964379)). This actually seems to be a quite delicate topic. – 0101100101 Aug 05 '14 at 13:55
  • What harm would possibly occur you think, if i use the code I've given above? you made me suspect – Tolgay Toklar Aug 05 '14 at 14:24
  • Most importantly you lose the advantage of fragments being interchangeable (see http://developer.android.com/guide/components/fragments.html for more on that). Beside that Google might decide to fix this "bug" and onClick will link to the underlying fragment instead of its container activity. In that case you'll have to switch to my solution without the edit anyway. – 0101100101 Aug 05 '14 at 14:33
  • @Tolgay... hi can you tell me wt is container in R.id.container represent...i saw ur question but i didnt get it, is it the baseActivity from which the fragement has created?? – kumar Mar 29 '16 at 19:26