ListFragment with different Layout - android

I am working on Fragment-ListView and having output showing in image.
every Click changes TextView of fragment2.till now ok.
fragmetn1 is for listView and fragment2 is for DifferentView.
now i want to change layout in fragment2 with click. e.g. as item2 is clicked,a layout with textView sets in fragment2. now with selection of item3, diferent layout with Button should be set to fragment2.
my getView code is here.
public void onListItemClick(ListView l, View v, int position, long id) {
DetailFrag frag = (DetailFrag) getFragmentManager().findFragmentById(R.id.frag_detail);
if (frag != null && frag.isInLayout()) {
frag.setText("item "+position+" selected");
}
}
is there other way to do this,plz also help that way.
any suggestion would be strongly appreciated.thanks in advance.

Try the following method
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
then you need to add your fragment to this fragmentTransaction with the following syntax.
fragmentTransaction.replace(R.id.detailFragment, layout1);
And finally you MUST commit your transaction. Otherwise changes will not persist.
fragmentTransaction.commit();

In my opinion you should use different fragments with different layout and using FragmentTransaction to replace the existing one.

Your approach likely works fine, but it is probably better to use a more loosely coupled approach where the ListFragment informs the hosting activity that an item has been clicked, and then the activity tells the "other" fragment to update.
No need to worry about constructing and replacing new fragments.
Sample activity
public class TestActivity extends Activity implements TestFragmentBListener {
private TestFragmentA mOtherFragment;
private TestFragmentB mListFrag;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mListFrag = (TestFragmentB) getFragmentManager().findFragmentById(R.id.fragment_b_list);
mOtherFragment = (TestFragmentA) getFragmentManager().findFragmentById(R.id.fragment_a_text);
}
#Override
public void onTestFragmentBItemCLicked(int position) {
// Implemented from TestFragmentB.TestFragmentBListener
mOtherFragment.setText("item " + position + " selected.");
}
}
Sample FragmentA (contains text.. this is not functional, only an example)
public class TestFragmentA extends Fragment {
public void setText(String text) {
}
}
Sample ListFragment that defines an interface for the sample activity to implement
public class TestFragmentB extends ListFragment {
private TestFragmentBListener mListener = null;
public interface TestFragmentBListener {
void onTestFragmentBItemCLicked(int position);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (TestFragmentBListener) activity;
} catch (ClassCastException ccex) {
// activity does not implement our listener
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if (mListener != null) {
mListener.onTestFragmentBItemCLicked(position);
}
}
}
and for the sake of completeness, here was my layout for the sample activity:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TestActivity" >
<fragment
android:id="#+id/fragment_a_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<fragment
android:id="#+id/fragment_b_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/fragment_a_text" />
</RelativeLayout>

Related

Open fragment from Fragment on button click

I am having trouble opening a fragment from within another fragment on the click of a button. Everything seems to make sense (to me) and I have tried playing about with my code (changing the layouts, replacing fragments etc) but nothing is working.
Here is my RoleFragment.java (The fragment which contains the button)
public class RolesFragment extends Fragment implements View.OnClickListener {
GridView gridView;
ArrayList<Players> playersList;
MyAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_viewroles, container, false);
gridView = (GridView) view.findViewById(R.id.gv_players);
Button nightround = (Button) view.findViewById(R.id.buttonNightRound);
nightround.setOnClickListener(this);
DatabaseHelper databaseHelper = new DatabaseHelper(getActivity());
playersList = new ArrayList<Players>();
playersList = databaseHelper.getPlayers();
adapter = new MyAdapter(getActivity(), playersList);
gridView.setAdapter(adapter);
return view;
}
#Override
public void onClick(View v) {
Fragment fragment = null;
switch (v.getId()) {
case R.id.buttonNightRound:
fragment = new NightRound();
replaceFragment(fragment);
break;
}
}
public void replaceFragment(Fragment someFragment) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, someFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
And this is my fragment_viewroles.xml file.
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.tuss.mafia.GameActivity" >
<Button
android:id="#+id/buttonNightRound"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Night Round"
android:onClick="FragmentNightRoundClick"
android:clickable="true"
android:layout_weight="2"/>
<GridView
android:id="#+id/gv_players"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:columnWidth="150dp"
android:horizontalSpacing="10dp"
android:verticalSpacing="10dp"
android:gravity="center"
android:layout_below="#id/buttonNightRound">
</GridView>
</RelativeLayout>
The trouble is, when I click the button nothing happens.
There some problems here.
First, you have to add a container with the id R.id.fragment_container inside your fragment like FrameLayout
which will store your new fragment.
If your want to open a fragment as a new screen, you have to put it inside a new activity. Fragments are piece of screens and should not be used without activities or view pagers.
Have a look at the Android deverlopers page: http://developer.android.com/training/basics/fragments/communicating.html#DefineInterface
Basically, you define an interface in your Fragment A, and let your Activity implement that Interface. Now you can call the interface method in your Fragment, and your Activity will receive the event. Now in your activity, you can call your second Fragment to update the textview with the received value
// You Activity implements your interface
public class YourActivity implements FragmentA.TextClicked{
#Override
public void sendText(String text){
// Get Fragment B
FraB frag = (FragB)
getSupportFragmentManager().findFragmentById(R.id.fragment_b);
frag.updateText(text);
}
}
// Fragment A defines an Interface, and calls the method when needed
public class FragA extends Fragment{
TextClicked mCallback;
public interface TextClicked{
public void sendText(String text);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (TextClicked) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement TextClicked");
}
}
public void someMethod(){
mCallback.sendText("YOUR TEXT");
}
#Override
public void onDetach() {
mCallback = null; // => avoid leaking, thanks #Deepscorn
super.onDetach();
}
}
// Fragment B has a public method to do something with the text
public class FragB extends Fragment{
public void updateText(String text){
// Here you have it
}
}
Try something like the following:
Fragment fragment = OtherFragment.newInstance();
android.support.v4.app.FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container_layout, fragment, "OtherFragment");// give your fragment container id in first parameter
transaction.addToBackStack(null); // if written, this transaction will be added to backstack
transaction.commit();

Reverse shared element transition on back

I am currently using the following code to transition a block on the right side of the screen to a shared element on the left:
FragmentDetail newFragment = FragmentDetail.newInstance(id);
setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.trans_move));
setExitTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.explode));
View block = view.findViewById(R.id.blocks);
block.setTransitionName("block");
newFragment.setSharedElementEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.trans_move));
newFragment.setEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.explode));
newFragment.setTransitionId(block.getTransitionName());
FragmentTransaction trans = getFragmentManager().beginTransaction();
trans.replace(R.id.container, newFragment);
trans.addToBackStack(null);
trans.addSharedElement(block, block.getTransitionName());
trans.commit();
This works exactly how I want, but I would like to reverse the effect upon pressing the back button, animating the item back in. As is, the explode animation plays, but the transition does not.
Any help is greatly appreciated.
Thanks
Josh
KOTLIN with Android Navigation Component
For anyone who's here looking for the answer to this question when you're using the Android Navigation component, you can make the reverse transition animation work by adding these lines to the onViewCreated function of the starting fragment:
postponeEnterTransition()
view.doOnPreDraw { startPostponedEnterTransition() }
You would generally use this if you are opening the second fragment by clicking on a RecyclerView item.
Let's say you have two fragments, A and B, and A commits a fragment transaction to start fragment B.
Then that means the exit and reenter transitions should be set on A and the enter and return transitions should be set on B.
It looks like you are calling setSharedElementReturnTransition on the calling fragment instead of the called fragment (newFragment, in this case), which might be causing the problem.
BTW, you should consider calling the set*****Transition() and setSharedElement*****Transition() methods in your fragment's onCreate() method instead of immediately before a fragment transaction is committed. If a fragment is destroyed and recreated, these transitions will be forgotten... so setting them in onCreate() is much safer.
switch from
trans.replace(R.id.container, newFragment);
to
trans.hide(oldFragment).add(R.id.container, newFragment).show(newFragment)
and it should work (as in my case).
reverting a shared fragment transition seems to only work if you hide the old one, instead of replacing it.
I have met the same problem with you.Buy I have found the solution.
You know, there are many causes for this problem. I just show my way.
Hope that can help you.
there are two fragments.
one have a RecyclerView widget:
ListFragment.java
public class ListFragment extends Fragment implements RecyclerItemInter {
#Bind(R.id.recycler_view)
RecyclerView recyclerView;
private OnListItemClickListener onListItemClickListener;
public void setOnListItemClickListener(ListFragment.OnListItemClickListener onListItemClickListener) {
this.onListItemClickListener = onListItemClickListener;
}
public ListFragment() {
}
public static ListFragment newInstance() {
ListFragment fragment = new ListFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_list, container, false);
ButterKnife.bind(this, view);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
RecyclerAdapter2 adapter = new RecyclerAdapter2(BEAUTY_BEANS);
recyclerView.setAdapter(adapter);
adapter.setItemInter(this);
return view;
}
private static final BeautyBean[] BEAUTY_BEANS = {
new BeautyBean("Avril Lavigne1", "Avril was born in Canada, the Canadian singer, songwriter creators, actors."),
new BeautyBean("Avril Lavigne2", "Avril was born in Canada, the Canadian singer, songwriter creators, actors."),
new BeautyBean("Avril Lavigne3", "Avril was born in Canada, the Canadian singer, songwriter creators, actors."),
new BeautyBean("Avril Lavigne4", "Avril was born in Canada, the Canadian singer, songwriter creators, actors."),
new BeautyBean("Avril Lavigne5", "Avril was born in Canada, the Canadian singer, songwriter creators, actors.")
};
#Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
#Override
public void onItemClick(View view, int position) {
}
#Override
public void onIvClick(RecyclerAdapter2.ViewHolder holder, int position) {
OtherFragment otherFragment = OtherFragment.newInstance();
otherFragment.setSharedElementEnterTransition(new CustomTransition());
otherFragment.setSharedElementReturnTransition(new CustomTransition());
/*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
otherFragment.setEnterTransition(new Fade());
setExitTransition(new Fade());
}*/
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_layout, otherFragment)
.addToBackStack(null)
.addSharedElement(holder.getPicIv(), getString(R.string.transition_img))
.commit();
}
then you should set the TransitionName to every ImageView in the RecyclerView:
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
if (items[position].getImageId() != 0) {
holder.getPicIv().setImageResource(items[position].getImageId());
}
ViewCompat.setTransitionName(holder.getPicIv(), String.valueOf(position) + "_beauty");
holder.getTitleTv().setText(items[position].getName());
holder.getDescTv().setText(items[position].getDesc());
holder.getLinearLayout().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (null != itemInter) {
itemInter.onItemClick(holder.itemView, position);
}
}
});
holder.getPicIv().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (null != itemInter) {
itemInter.onIvClick(holder, position);
}
}
});
}
click the list jump to the OtherFragment.
OtherFragment.java
public class OtherFragment extends Fragment {
public OtherFragment() {
}
public static OtherFragment newInstance() {
OtherFragment fragment = new OtherFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_other, container, false);
}
}
fragment_other.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.jacksen.supportlibrarydemo.fragment.OtherFragment">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/bg_detail_header"
android:transitionName="#string/transition_img" />
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/ic_backup_white_36dp"
android:transitionName="#string/transition_fab"
app:borderWidth="0dp"
app:elevation="5dp"
app:pressedTranslationZ="10dp"
app:rippleColor="#color/color_gray" />
the crux of the problem is in this xml.
at the beginning, i set the attribute "transitionName" on and its father layout.
Actually we don't need to add the attribute on father Layout.
Just add transitionName to what you want to transform.
OK, that is my solution.
The Joe Muller answer is correct, I wrote it for Java
#Override
public void onViewCreated(#NonNull final View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
postponeEnterTransition();
view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
startPostponedEnterTransition();
view.getViewTreeObserver().removeOnPreDrawListener(this);
return false;
}
});
}
This resolve issue if the start transition is inside an adapter

Keeping List View and View Pager in sync

Forgive me if the title is a little vague, I'm having trouble wording this issue, which is also why I am unable to find any examples via Google.
I'm using the master/detail flow layout in my application as I mostly develop on a tablet.
The implementation follows the usual pattern, two Fragments being contained in one Activity and I have it working perfectly. In this case the detail is actually a ViewPager, with the ViewPager and the ListView being alternate forms of displaying the same data.
So selecting an item in the list will scroll the ViewPager to the position and swiping across will update the selected item in the list.
Here's what I have so far:
MainActivity.java
public class MainActivity extends ActionBarActivity
implements VideoListFragment.Callbacks, VideoDetailFragment.Callbacks {
#Override
public void onItemSelected(String callingClass, int id) {
//Work out which one we're updating based on which class called this method
if (callingClass == VideoListFragment.VIDEO_LIST_ID) {
//Update the VideoDetail
VideoDetailFragment fragment = (VideoDetailFragment) getSupportFragmentManager().findFragmentById(R.id.content_pane);
if (fragment != null) {
fragment.setViewPagerPosition(id);
} else {
Bundle arguments = new Bundle();
arguments.putInt(VideoDetailFragment.VIDEO_ID, id);
fragment = new VideoDetailFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.content_pane, fragment)
.commit();
}
} else if (callingClass == VideoDetailFragment.VIDEO_DETAIL_ID) {
//Update the VideoList
VideoListFragment fragment = (VideoListFragment) getSupportFragmentManager().findFragmentById(R.id.list_pane);
fragment.setSelection(id);
}
}
}
ListFragment.java
public class ListFragment extends ListFragment {
public interface Callbacks {
public void onItemSelected(String callingClass, int id);
}
#Override
public void onListItemClick(ListView listView, View view, int position, long id) {
super.onListItemClick(listView, view, position, id);
setSelection(position);
mCallbacks.onItemSelected(VIDEO_LIST_ID, position);
}
#Override
public void setSelection(int position) {
mListView.setItemChecked(position, true);
mListView.smoothScrollToPosition(position);
}
}
VideoDetailFragment.java
public class VideoDetailFragment extends Fragment {
public interface Callbacks {
public void onItemSelected(String callingClass, int id);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Left
if (mListPosition > position + positionOffset) {
mCallbacks.onItemSelected(VIDEO_DETAIL_ID, position);
} else //Right
{
mCallbacks.onItemSelected(VIDEO_DETAIL_ID, position);
}
}
}
It's a pretty basic system but it works for the most part, the only problem is that the system often calls onPageScrolled when the views are being refreshed, such as when new data has downloaded and notifyDatasetChanged is called. This leads to a lot of to and fro-ing with the listview selection flying up and down and looks tacky overall.
A good example of what I want is the GMail app, it has the master detail flow and updates seamlessly. Is there any code examples of this anywhere?
Thanks in advance.

Calling fragment from a list adapter

I am using sliding menu/drawer pattern in my app. So the main activity has a leftView which is a ListFragment named topicsFragment() which loads set of topic items. When an item/topic is clicked it replaces the fragment on main view by calling the FeedsFragment(tag). FeedsFragment uses arraylist adapter to load the feeds which has various clickable items in each list item. I want to fetch another instance on the feedsFragment(tag) when an item is clicked within a list item.
holder.contextView= (TextView) newsView.findViewById(R.id.arcHeader);
if (item.hasArc()) {
holder.contextView.setVisibility(View.VISIBLE);
String arc;
try {
arc=item.getarc();
holder.contextView.setText(arc);
holder.contextView.setOnClickListener(new View.OnClickListener() {
//currently it loads a class
#Override
public void onClick(View v) {
Intent i = new Intent(context, SomeClass.class);
i.putExtra("tag", arc);
context.startActivity(i);
}
});
} catch (JSONException e) {
e.printStackTrace();
}
} else {
holder.contextView.setVisibility(View.GONE);
}
Currently it loads a new class. I want to define a fragment and then pass to main activity to replace with the current view but I cant use getSupportFragmentManager() inside an adapter class but only in a fragment or fragment activity. What should be an alternative to sweeping in a fragment from an adapter?
What I did was create this method in my main activity and just called it from other classes to change the fragment:
public void switchContent(Fragment fragment) {
mContent = fragment;
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, fragment).commit();
slidemenu.showContent();
}
Solved it by using the context passed in the list adapter:
#Override
public void onClick(View v) {
Fragment newFragment = new ListFragmentClass(tag);
if (newFragment != null)
switchFragment(newFragment);
}
private void switchFragment(Fragment newFragment) {
if (context == null)
return;
if (context instanceof MainActivity) {
MainActivity feeds = (MainActivity) context;
feeds.switchContent(newFragment);
}
}
Here switchContent is method defined in your main activity for switching/replacing fragment as given in answer by Justin V.
Pass getFragmentManager() as a parameter in constructor of your adapter and use that.
Use an Interface to connect your side drawer ListFragment to the main activity. For example:
public class LeftDrawer extends ListFragment{
private DrawerCallback mCallback;
public interface DrawerCallback{
public void onListClick(String tag);
}
public void setCallback(DrawerCallback callback){
mCallback = callback;
}
}
As Fragments should have an empty constructor, use a public method within your Fragment to set the callback before completing the FragmentTransaction adding it to your drawer. At this point all that is left is notifying your Fragment that a click has occurred. What you should do is actually catch the click in your ListFragment directly rather than adding on onClickListener to every view in your adapter.
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
/*
* Get item at the clicked position from your adapter and
* get its string tag before triggering interface
*/
mCallback.onListClick(tag);
}
Use the onListItemClick method to do this. You will get the list position that was clicked and can easily then get that item from your adapter and get its tag value to pass back to your host activity.

Error inflating class fragment error

I have a Main activity with two master detail Fragments.I am trying to implement like "Multiple fragments, multiple activities" method.
layout folder
activity_main.xml
<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=".MoneyActivity"
android:id="#+id/fragment_container" >
<fragment class="com.mysite.money.AFragment"
android:id="#+id/AFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
layout-large folder activity_main.xml
<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"
tools:context=".MoneyActivity"
android:id="#+id/fragment_container"
android:orientation="horizontal" >
<fragment class="com.mysite.money.AFragment"
android:id="#+id/AFragment"
android:layout_width="#dimen/action_bar_title_text_size"
android:layout_height="match_parent"/>
<fragment class="com.mysite.money.BFragment"
android:id="#+id/BFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
I got error like below(when run on tablet-layout-large):
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mysite.money/com.mysite.money.MoneyActivity}: android.view.InflateException: Binary XML file line #15: Error inflating class fragment
I checked class names of fragments properly.
I think i got error BFragment
BFragment:
public class BFragment extends SherlockFragment {
String selectedItem="";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int size = getArguments().size();
if(size>0)
{
selectedItem = getArguments().getString("position").toString();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
TextView textView=new TextView(inflater.getContext());
textView.setText("Selected Item->"+selectedItem);
return textView;
}
}
OnItemSelected in my mainActivity(Associated with fragment A)
**#Override
public void onItemSelected(String id) {
BFragment displayFrag = (BFragment) getSupportFragmentManager().findFragmentById(new BFragment().getId());
if (displayFrag == null) {
// DisplayFragment (Fragment B) is not in the layout (handset layout),
// so start DisplayActivity (Activity B)
// and pass it the info about the selected item
Intent intent = new Intent(this, BActivity.class);
intent.putExtra("position", id);
Log.i("innodea", "position->"+id);
startActivity(intent);
} else {
// DisplayFragment (Fragment B) is in the layout (tablet layout),
// so tell the fragment to update
//displayFrag.updateContent(id);
}
}**
AFragment:
public class AFragment extends SherlockListFragment {
private View inflate;
private Callbacks mCallbacks = sDummyCallbacks;
private int mActivatedPosition= ListView.INVALID_POSITION;
private static final String STATE_ACTIVATED_POSITION = "activated_position";
public interface Callbacks {
public void onItemSelected(String id);
}
/**
* A dummy implementation of the {#link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
public void onItemSelected(String id) {
}
};
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException(
"Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(getActivity(),android.R.layout.simple_list_item_activated_1,android.R.id.text1, DummyContent.ITEMS));
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Restore the previously serialized activated item position.
if (savedInstanceState != null
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState
.getInt(STATE_ACTIVATED_POSITION));
}
}
#Override
public void onDetach() {
super.onDetach();
// Reset the active callbacks interface to the dummy implementation.
mCallbacks = sDummyCallbacks;
}
#Override
public void onListItemClick(ListView listView, View view, int position,long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mActivatedPosition != ListView.INVALID_POSITION) {
// Serialize and persist the activated item position.
outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
}
}
/**
* Turns on activate-on-click mode. When this mode is on, list items will be
* given the 'activated' state when touched.
*/
public void setActivateOnItemClick(boolean activateOnItemClick) {
// When setting CHOICE_MODE_SINGLE, ListView will automatically
// give items the 'activated' state when touched.
getListView().setChoiceMode(
activateOnItemClick ? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
}
private void setActivatedPosition(int position) {
if (position == ListView.INVALID_POSITION) {
getListView().setItemChecked(mActivatedPosition, false);
} else {
getListView().setItemChecked(position, true);
}
mActivatedPosition = position;
}
}
The exception android.view.InflateException: Binary XML file line: #... Error inflating class fragment might happen if you manipulate with getActivity() inside your fragment before onActivityCreated() get called. In such case you receive a wrong activity reference and can't rely on that.
For instance the next pattern is wrong:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
final View view = inflater.inflate(R.layout..., container, false);
Button button = getActivity().findViewById(R.id...);
button.setOnClickListener(...); - another problem: button is null
return view;
}
Adding Unique ID for the Static Fragment is required. I found it after carefully looking in Logs for error. CLick on below link to see error details:
Error Inspection in logs
No need for FragmentActivity as suggested in many posts. AppCompatActivity is fine.
So, code like below works just fine.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="Customize your Android: " />
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.android.android_me.ui.MasterListFragment"
android:id="#+id/StaticFragment"/>
</LinearLayout>
Your fragment code is most likely broken and simply crashes on creation which ends in failure of inflation. Plant breakpoints on each fragment onCreateView() and related methods called in during fragment creation or try to instantiate the fragment by hand (new AFragment()) and attaching it to The Layout to see where exactly if fails.
You need to import the Fragment class from android.support.v4.app.Fragment instead of android.app.Fragment.
import android.support.v4.app.Fragment;
And in the XML file of the activity where you intend to use this fragment, you need to use:
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/map_fragment"
name="yourpackagname.yourfragmentclass"/>
//package name here, is the name of folder which is in java directory.

Categories

Resources