Vishal Vijay Vishal Vijay - 1 month ago 10
Android Question

Why can't I use the same id in different layout for different fragements in ViewPager

I have 2 fragments in my application,

Fragment1
and
Fragment2
. Both are using different layouts called
content_view1
and
content_view2
. And I put both fragment into a
ViewPager
. Now see the code :

MainActivity.java


public class MainActivity extends FragmentActivity {

public ViewPager vp;
FragmentAdapter fragmentAdapter;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
vp = new ViewPager(this);
vp.setId("VP".hashCode());
fragmentAdapter = new FragmentAdapter(
getSupportFragmentManager());
vp.setAdapter(fragmentAdapter);
setContentView(vp);
vp.setCurrentItem(0);
}

}




Fragment1.java



public class Fragment1 extends Fragment {

MainActivity mainActivity;

public Fragment1() {
setRetainInstance(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mainActivity=(MainActivity)getActivity();
return inflater.inflate(R.layout.content_view1, null);
}

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

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((TextView)mainActivity.findViewById(R.id.haiTextView)).setText("Hello");
}
}




Fragment2.java



public class Fragment2 extends Fragment {

MainActivity mainActivity;

public Fragment2() {
setRetainInstance(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mainActivity=(MainActivity)getActivity();
return inflater.inflate(R.layout.content_view2, null);
}

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

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((TextView)mainActivity.findViewById(R.id.haiTextView)).setText("Hai");
}
}


FragmentAdapter.java



public class FragmentAdapter extends FragmentPagerAdapter {

private ArrayList<Fragment> mFragments;

public FragmentAdapter(FragmentManager fm) {
super(fm);
mFragments = new ArrayList<Fragment>();
mFragments.add(new Fragment1());
mFragments.add(new Fragment2());
}

@Override
public int getCount() {
return mFragments.size();
}

@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
}




content_view1.xml


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal" >

<TextView
android:id="@+id/haiTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="true" />

</FrameLayout>




content_view2.xml


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal" >

<TextView
android:id="@+id/haiTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="true" />

</FrameLayout>




Now you see both layout has one textView with same
id
.

When I run this application, the fragment1's
TextView
has text "hai" and fragment2's
TextView
has text "". But what I'm expecting is, the fragment1's
TextView
should have text "Hello" and fragment2's
TextView
should have text "hai".


Ok now I changed the
TextView
id of
content_view2.xml
to
haiTextView2
. Did the same in
Fragment2.java
also. Now the application is working perfectly as I expected.


Now my questions:


1) Why I did't get the expected out put when I keep both the
TextView
id same?

2) Why can't I use same ids here?

Answer

1) Why I did't get the expected out put when I keep both the TextView id same?

2) Why can't I use same ids here?

That is happening because of this line:

((TextView)mainActivity.findViewById(R.id.haiTextView)).setText("Hai");

The problem is the findViewById() method will return the first occurrence of a View with the provided id(it also doesn't differentiate between the layouts of the two fragments), so when you're setting the text in either the first or second fragment the TextView that gets set is the first one(the one from the second fragment is left untouched).

On the other hand, when you use different ids the proper TextViews will get selected.

You should avoid looking for the views of a Fragment using the Activity reference, fragments should be designed as loosely coupled components(it doesn't make any sense to look for the fragment's views using the activity when you could simply use getView().findViewById(etc)). Also, you should really avoid using setRetainInstance() with fragments used in a ViewPager.