android viewpager inside another viewpager - android

I'm trying to have a viewpager with few views (let's say 5?) and in one of the views (let's say 3rd view?) I have to put another viewpager so after searching for a while, I've come up with some questions which I couldn't get the exact answer for my situtation.
How is it possible to implement a viewpager inside a fragment of another viewpager?
If it's possible to do the above task, how's the touch function will be handled for viewpagers ? Isn't changing views for the inner viewpager gonna affect the outer one?
I don't really need a code kinda solution but more like a concept kinda solution, so I'm not asking for anyone to do my coding, but I've been quiet away from android and I rather to hear the new concepts from the pros.
thanks in advance.
Edit:
Ok I managed to do it at some point but another problem I'm facing now.
here is the call to the fragment which contains my viewpager:
Fragment fragment = new Fragment();
switch(position)
{
case 0: fragment = new CalendarFragment();break;
case 1: fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, 2);
fragment.setArguments(args);break;
}
return fragment;
and this is the oncreate of calendarFragment class:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View cal = inflater.inflate(R.layout.calendar, container, false);
viewPager = (ViewPager) cal.findViewById(R.id.calendar_pager);
viewPager.setOnTouchListener( new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN && v instanceof ViewGroup) {
((ViewGroup) v).requestDisallowInterceptTouchEvent(true);
}
return false;
}
});
viewPager.setAdapter(createCalendarAdaptor());
viewPager.setCurrentItem(MONTHS_LIMIT / 2);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int arg0) {
//updateResetButtonState();
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
});
return cal;
}
and I get the calendar in the first fragment and it works just fine and I can easily scroll to next page, and then I can easily move back to the first page, but when I move to 3rd page and then I go back to first page which is my other viewpager it cause an error:
java.lang.IllegalStateException: Recursive entry to executePendingTransactions
I'm not quiet sure why is it happening, I've done some searching and it appears it's because I'm using a viewpager inside a fragment...
Any help would be appreciated.

Related

PagerAdapter and ViewPager start a new fragment over the current visible view

I have a ViewPager with a PagerAdapter that is called from another fragment, a main fragment if you will.
My PagerAdapter is showing the user images and the user can swipe between them using ViewPager.
I've registered an onClick listener for every image and it seems to work as expected, at least it returns the correct position if I debug the position from instantiateItem.
The problem is that this onClick is supposed to start a new fragment, like an overlay over the image that the user clicked on but it doesn't start the fragment over the current image that the user clicked on for some reason.
Example of what I mean:
On page one onClick it starts the fragment at the correct position, (overlaying the current visible view).
On page two onClick it starts the fragment on page 1 (not in the visible view and not where the onClick fired).
On page three onClick it starts the fragment on page 2 (not in the visible view and not where the onClick fired).
Code:
MainFragment.java
public class MainFragment extends Fragment implements AdapterView.OnItemSelectedListener {
ViewPager viewPager;
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
viewPager = (ViewPager) getView().findViewById(R.id.viewPager);
swipeAdapter = new SwipeAdapter(getActivity(), getContext(), stringFetchedName, stringFetchedUserID, stringFetchedUsername, stringFetchedRating, stringFetchedDescription, stringFetchedDate);
viewPager.setAdapter(swipeAdapter);
}
}
SwipeAdapter.java
public class SwipeAdapter extends PagerAdapter {
FragmentActivity activity;
Context context;
String names[], userid[], username[], rating[], description[], date[];
LayoutInflater layoutInflater;
ImageView imageView;
public View itemView;
public SwipeAdapter(FragmentActivity activity, Context context, String names[], String userid[], String username[], String rating[], String description[], String date[]) {
this.activity = activity;
this.context = context;
this.names = names;
this.userid = userid;
this.username = username;
this.rating = rating;
this.description = description;
this.date = date;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return names.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((View) object);
}
#Override
public Object instantiateItem(final ViewGroup container, final int position) {
final View itemView = layoutInflater.inflate(R.layout.imageswap, container, false);
imageView = itemView.findViewById(R.id.imageView);
container.addView(itemView);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (itemView.findViewById(R.id.userText).isShown()) {
showImageOverlay(v);
} else {
hideImageOverlay(v);
}
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
public void showImageOverlay(View view) {
Fragment fragment = new ImageOverlayFragment().newInstance("0", "0");
FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.imageSwap, fragment, IMAGE_OVERLAY);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
public void hideImageOverlay(View view) {
Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag(IMAGE_OVERLAY);
if(fragment != null) {
activity.getSupportFragmentManager().beginTransaction().remove(fragment).commit();
}
}
}
How can I make sure that the new fragment ImageOverlayFragment I start is started on top of the image that was clicked, like how could I take the position from instantiateItem into account etc? or what should I do?
If I debug Log.d("debug", "Clicked position:" + position); inside the imageView OnClickListener it gives me the correct position but when I call showImageOverlay(v), it seems like it always starts the fragment on the view to the left of my currently visual view?
Note:
I'm passing a FragmentActivity to the SwipeAdapter from the MainFragment which is why I can access getSupportFragmentManager().
Update:
I tried to use FragmentStatePagerAdapter instead of PagerAdapter as suggested by SO and the result is still the same. The onClick event is sending the correct position and I can toggle the visibility of visible elements within the onClick event etc but I still cannot start the new fragment over the view of where the user clicked. The new fragment still starts to the left, and not in the view of where the user clicked. Problem still remains.
fragmentTransaction.replace(R.id.imageSwap, fragment, IMAGE_OVERLAY);
You are using your activity's TransactionManager to start you overlay fragment. In the above code, what I am guessing is that you are giving the ID of the container viewgroup of , parent of ImageView in its layout file. In a ViewAdapter not the currently visible fragment is initialized or view is inflated, but adjacent fragments/views also. That means your view hierarchy from activity root contains more than one layout with the ID you provide for fragment transaction. When activity searches its view hierarchy, it will return the first view it reaches with given ID. In your case, when you are not on the first page of adapter, this first matching view will be inside the leftmost page inside ViewPager. ViewPager - by default - uses one view on left and one view on right of the visible page in created state. That is why you see your fragment is instantiated on the page before the one you want it to be.
As a solution, you can consider using fragments inside Pager instead of plain views. Every fragment has a 'childFragmentManager' that u can use to start your new fragment upon click.
I hope this helps.
I had a similar issue with FragmentStatePagerAdapter, and what worked had much to do with two of the adapter methods:
instantiateItem - "Create the page for the given position."
setPrimaryItem - "Called to inform the adapter of which item is currently considered to be the "primary", that is the one show to the user as the current page."
Because of the way the adapter works, where it instantiates the fragments before they are displayed, the instantiateItem method is called for fragments or slides that are not in view (apart from the first item). If you can override setPrimaryItem, and then leave the UI/view set up in instantiateItem, and then the rest of the logic (listener with the show/hide overlay) in setPrimaryItem, you can make sure the listener and the fragment are set to the currently active view/fragment.
Let me know if that makes sense to you

Shared Element Transition + Fragment + RecyclerView + ViewPager

I am implementing a gallery app, which has a Fragment that holds a RecyclerView with images, onClick of an image I go to ViewPager to cycle through images.
For now, I am trying to implement just the entry animation like in this video. The problem is the animation just doesn't work, I am obviously missing something (just showing code which is relevant to transitions):
ViewPager:
public class ViewPagerFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_viewpager, container, false);
Transition transition = TransitionInflater.from(getContext()).inflateTransition(R.transition.fragment_transition);
setSharedElementEnterTransition(transition);
postponeEnterTransition();
return view;
}
GridAdapter:
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder> {
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.setPhotoImage(new File(mArrayOfPhotos.get(position).photo));
ViewCompat.setTransitionName(holder.photoImage, mPhotoObjects.get(position).photo);
}
#Override
public void onClick(View view) {
// pass an image view that is being clicked...
// ...via listener to MainActivity from where ViewPagerFragment is started
mListener.onImageSelected(photoImage, getAdapterPosition());
}
}
In MainActivity I instantiate ViewPagerFragment in onClick:
#Override
public void onImageSelected(View view, int clickedImagePosition) {
ViewPagerFragment fragment = new ViewPagerFragment();
Bundle bundle = new Bundle();
bundle.putInt(ViewPagerFragment.KEY_IMAGE_INDEX, clickedImagePosition);
fragment.setArguments(bundle);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// view is an image view that was clicked
fragmentTransaction.addSharedElement(view, ViewCompat.getTransitionName(view));
fragmentTransaction.setReorderingAllowed(true);
fragmentTransaction.replace(R.id.fragment_placeholder, fragment, VIEWPAGER_FRAGMENT);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
And finally in ImageFragment(which is a single image in ViewPager) I have:
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
mFullImage.setTransitionName(transitionName);
Glide.with(getActivity())
.load(myImage)
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL))
.listener(new RequestListener<Drawable>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
getParentFragment().startPostponedEnterTransition();
return false;
}
#Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
getParentFragment().startPostponedEnterTransition();
return false;
}
})
.into(mFullImage);
return view;
}
Transition name is not the problem, it is unique, and it is passed normally between all the fragments. I have followed this article and read many others, but it feels like a small bit is missing in my code.
EDIT:
I was able to localize the problem I think. The transition worked several times randomly, apparently, it happens because images are not ready when I am making the transition. I tried to call postponeEnterTransition() in MainActivity onCreate but still doesn't work. Images are passed to the ImageFragment through the Bundle. Still looking.
EDIT:
I believe I found the problem, I have a fragment, that has a TabLayout inside it, which has 2 fragments, one displaying all photos, and one displaying photos that are tagged as favorite. And they both use the same RecyclerView. The shared element transition works only if the photo is in one section at the same time, once I tag a photo as favorite it appears in all photos as well as favorite photos and the transition no longer works. It probably happens because the transition is no longer unique. Is there a way to solve this? Considering the fact that both fragments use the same RecyclerView, and the same adapter class.
I finally got it to work, the problem was in transition names. The transitions are also working with the support Transition library.
At first, the transition was not working at all, so I used a method that I found here to postpone the transition, it's a good link that explains transitions:
private void scheduleStartPostponedTransition(final View sharedElement) {
sharedElement.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
sharedElement.getViewTreeObserver().removeOnPreDrawListener(this);
getParentFragment().startPostponedEnterTransition();
return true;
}
});
}
In my case, I have nested fragments, a ViewPagerFragment that contains a ViewPager and manages the fragments (ImageFragment) using ImageAdapter. I call postponeEnterTransition() from the ViewPagerFragment and that is why I am using getParentFragment().
I used the method scheduleStartPostoponedTransition in Glide onLoadFailed and onResourceReady().
The main problem was in my implementation. I have a fragment that contains a TabLayout with 2 tabs, each containing a fragment with a RecyclerView. One fragment shows all photos and other shows favorite photos. The transitions were working fine (after some alteration that I mentioned above) if a photo was only in one tab, but as soon as I marked it as favorite, it wouldn't work in either tab. Which means that two tabs had a photo with the same transition name.
My solution was to pass an integer to the GridAdapter depending on which fragment was shown (1 for all photos and 2 for favorite photos) and set it as a transition name:
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder> {
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.setPhotoImage(new File(mArrayOfPhotos.get(position).photo));
ViewCompat.setTransitionName(holder.photoImage, mPhotoObjects.get(position).photo + fragmentNumber);
}
}
And then pass this number to the ImageFragment and set it there too. After that, it started to work because every photo now had a different transition name.
Also if you are using a support version of transitions make sure you have the support library version 27.0.0 or above, as they fixed the transitions in this version.

How to display images in Android and change it by swipe right/left?

I want to add an introduction to my Android application, to inform the user about how the app works. This intro will be displayed only, if the preferred settings intro will be false. So in this intro, there will be 3 images and at the end, there will be a page, with some text and two buttons, to enable the user to access the application, by making a login. The change between each image, will be made with a swipe movement, (so right to left +, left to right -). How Can I do ?
This can be done via the use of Fragments and ViewPager and FragmentPagerAdapter. Look at this documentation:
FragmentPagerAdapter: http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html
ViewPager:
http://developer.android.com/reference/android/support/v4/view/ViewPager.html
You can have one fragment that is instantiated based on the id in the ViewPager, and that id will indicate which image to show in your image fragment. So for three images, you instantiate a new fragment that sets the image in the fragment based on the current page in the FragmentPagerAdapter. The second fragment can be one for the login buttons and text you want at the end.
Ex for adapter defined in your FragmentActivity (or AppCompatActivity)
public class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
if(position < 3)
return ImageFragment.newInstance(position);
else
return new LoginFragment();
}
}
Ex for the image fragment for the various images in your introduction:
public static class ImageFragment extends Fragment{
private int mPosition;
public ImageFragment(){
}
public static ImageFragment newInstance(int pos){
ImageFragment frag = new ImageFragment();
Bundle args = new Bundle();
args.putInt("pos", pos);
frag.setArguments(args);
return frag;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPosition = getArguments().getInt("pos");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_image, container, false);
ImageView backgroundView = (ImageView) v.findViewById(R.id.background_image);
switch(mPosition){
case 0:
//set background view image 1
case 1:
//set background view image 2
default:
//set background view image 3
}
return v;
}
}
I would recommend using a ViewPager. Check out this tutorial from the Developer Guide
http://developer.android.com/training/animation/screen-slide.html
If you want to add functionality to each of these pages instead of having just images then perhaps you can implement a fragmentStatePagerAdapter and then put all the functionality in each fragment. Here is a tutorial to implement one.
http://www.truiton.com/2013/05/android-fragmentstatepageradapter-example/
I think we can do it by using recycler view itself.
Using PagerSnapHelper layout manager in recycler view, we can implement swipe to change images.
recyclerView.setLayoutManager(new LinearLayoutManager(this,
LinearLayoutManager.HORIZONTAL, false));
// add pager behavior
PagerSnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);

Android Fragment from Layout - Retain variable data

I've been searching for hours and tried numerous methods but cannot seem to grasp my head around the idea / figure out how to retain/restore data in a ViewPager Fragment when it is destroyed and then recreated.
Here is what I have -
An activity where I setup the ViewPager and PageAdapter
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_pager);
//Setup pager and adapter
mPager = (ViewPager) findViewById(R.id.viewpager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
My PageAdapter where I setup a fragment with a bundle using .newInstance()
#Override
public Fragment getItem(int position) {
ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
return fragment.newInstance(position);
}
My Fragment that has a layout that includes a TextView that shows the user a question, a picture, and two True/False buttons. New instance is returned back to the Adapter.
public static ScreenSlidePageFragment newInstance(int position) {
ScreenSlidePageFragment fragment = new ScreenSlidePageFragment();
Bundle args = new Bundle();
args.putInt("page_position", position + 1);
fragment.setArguments(args);
return fragment;
}
//the fragment is newly created for the first time or recreated when exiting the view
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_main, parent, false);
//Handle a question being displayed on each fragment
count = getArguments().getInt("page_position") - 1;
mQuestionText = (TextView)v.findViewById(R.id.questionText);
mQuestionText.setText(bank.get(count).getQuestion());
//change the image depending on correct / incorrect answer
mPhoto = (ImageView)v.findViewById(R.id.imageView);
trueButton = (Button)v.findViewById(R.id.true_button);
falseButton = (Button)v.findViewById(R.id.false_button);
//True Button is pressed
trueButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(bank.get(count).getAnswer()) {
mPhoto.setImageResource(R.drawable.right);
clickable = false;
}
else {
mPhoto.setImageResource(R.drawable.wrong);
clickable = false;
}
trueButton.setClickable(clickable);
falseButton.setClickable(clickable);
}
});
What I cannot figure out for the life of me, is how to retain/save that fact that the user has pressed a button and which picture to display when the fragment is restored. I have tried a number of options using onResume(), getArguments(), onSaveInstanceState(), onActivityCreated() etc but none of them seem to work.
I can fix the problem by keeping all my ViewPager pages alive using setOffscreenPageLimit(total pages) but have read this is a bad idea since it takes up a large amount of memory.
Here is an example that I use that can help you where an ArrayList of urls for pictures is saved for later when the view is recreated, you need to override onSavedInstanceState and save your variables in a bundle, then retrieve the values from the bundle when the view is created again, hope this can help
ArrayList<String> picutersUrl = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState!=null)
{
picutersUrl = savedInstanceState.getStringArrayList("My Pictures");
}
#Override
protected void onSaveInstanceState(Bundle bundle)
{
super.onSaveInstanceState(bundle);
bundle.putStringArrayList("My Pictures", picutersUrl );
}
I too have used PagerAdapter to support few static tab widgets. I think you need to add code to ScreenSlidePagerAdapter. Google webpage at PagerAdapter.
Note and read the details on override method instantiateItem. This is where you populate the UI.
Code example for ScreenSlidePagerAdapterfrom (PagerAdapter subclass), using your posted code:
#Override
public Object instantiateItem(ViewGroup container, int position) {
View v = inflater.inflate(R.layout.fragment_main, parent, false);
...
trueButton = (Button)v.findViewById(R.id.true_button);
}
In reality with Views in this framework, you're responsible on saving the state of UI elements. In my ListView, I am caching and saving up to 100 rows of data and refreshes it in an Adapter, for example. For caching, I created custom class containing the UI data.

Dynamic UI with sliding menu and actionbarsherlock

Trying to achieve a dynamic UI with facebook like sliding menu and actionbarsherlock
.First i have look into android documentation which introduce fragment to handle dynamic button. But with no luck and a week time , i still can't get it to work anyhow , i guess is my misunderstand on android concept.The slidingbar and actionbarsherlock work without any problem.
I have a HomeScreen.java which contain all my menu and presetation stage
and so far i have created a pagerAdapter1.java that extends FragmentPagerAdapter
, and three example fragment class that handle my work which is task1.java,task2.java
,task3.java simple enough
here is part of my code
HomeScreen.java
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.slidingmenu.lib.SlidingMenu;
import com.slidingmenu.lib.app.SlidingFragmentActivity;
public class HomeScreen extends SlidingFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_screen);
setBehindContentView(R.layout.menu_frame);
}
PagerAdapter1.java
public class PagerAdapter1 extends FragmentPagerAdapter {
private List<Fragment> fragments;
public PagerAdapter1(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
public Fragment getItem(int position) {
return this.fragments.get(position);
}
public int getCount() {
return this.fragments.size();
}
}
and three task1.java,2,3
import android.support.v4.app.Fragment;
public class Tab1Fragment extends Fragment{
onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
return null;
}
return (LinearLayout)inflater.inflate(R.layout.tab_frag1_layout, container, false);
}
I think its better to explain my problem with picture
A homescreen which is a presetation stage , whenever user click on menu , this page will change to the page he want
and this is my menu
My problem is how do i include this 3 fragment into my homescreen ? i have tried so many tutorial but it doesn't work in my situation.Most tutorial are creating fragment with code, i just want to include my 3 task into it
I´ll try to explain this sample code and you use for your need.
This is the ListFragment of your BehindContent (SlidingMenu):
public class ColorMenuFragment extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.list, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String[] colors = getResources().getStringArray(R.array.color_names);
ArrayAdapter<String> colorAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1, colors);
setListAdapter(colorAdapter);
//This array is only to fill SlidingMenu with a Simple String Color.
//I used MergeAdapter from Commonsware to create a very nice SlidingMenu.
}
#Override
public void onListItemClick(ListView lv, View v, int position, long id) {
//This switch case is a listener to select wish item user have been selected, so it Call
//ColorFragment, you can change to Task1Fragment, Task2Fragment, Task3Fragment.
Fragment newContent = null;
switch (position) {
case 0:
newContent = new ColorFragment(R.color.red);
break;
case 1:
newContent = new ColorFragment(R.color.green);
break;
case 2:
newContent = new ColorFragment(R.color.blue);
break;
case 3:
newContent = new ColorFragment(android.R.color.white);
break;
case 4:
newContent = new ColorFragment(android.R.color.black);
break;
}
if (newContent != null)
switchFragment(newContent);
}
// the meat of switching the above fragment
private void switchFragment(Fragment fragment) {
if (getActivity() == null)
return;
if (getActivity() instanceof FragmentChangeActivity) {
FragmentChangeActivity fca = (FragmentChangeActivity) getActivity();
fca.switchContent(fragment);
} else if (getActivity() instanceof ResponsiveUIActivity) {
ResponsiveUIActivity ra = (ResponsiveUIActivity) getActivity();
ra.switchContent(fragment);
}
}
}
Here is your BaseActivity Class:
It dont have swipe, as I could understand, you don't need this.
public class FragmentChangeActivity extends BaseActivity {
private Fragment mContent;
public FragmentChangeActivity() {
super(R.string.changing_fragments);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set the Above View
if (savedInstanceState != null)
mContent = getSupportFragmentManager().getFragment(savedInstanceState, "mContent");
if (mContent == null)
mContent = new ColorFragment(R.color.red);
// set the Above View
//This will be the first AboveView
setContentView(R.layout.content_frame);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, mContent)
.commit();
// set the Behind View
//This is the SlidingMenu
setBehindContentView(R.layout.menu_frame);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.menu_frame, new ColorMenuFragment())
.commit();
// customize the SlidingMenu
//This is opcional
getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "mContent", mContent);
}
public void switchContent(Fragment fragment) {
// the meat of switching fragment
mContent = fragment;
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
getSlidingMenu().showContent();
}
}
Ok, So If you want to change the ColorFragment to anything else, do this:
First, choice the item that you want to use:
case 0:
newContent = new ColorFragment(R.color.red);
break;
to:
case 0:
newContent = new ArrayListFragment();
break;
I have made just a arraylist, it is just a simple example, you can do a lot of thing, then you can read about Fragment to learn how to do different things.
public class ArrayListFragment extends ListFragment {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, Listnames.TITLES));
//Listnames is a class with String[] TITLES;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Log.i("FragmentList2", "Item clicked: " + id);
String item = (String) getListAdapter().getItem(position);
Toast.makeText(getActivity(), item, Toast.LENGTH_LONG).show();
}
}
Well, if you misunderstood something, just tell me.
My problem is how do i include this 3 fragment into my homescreen ?
It really depends on how do you want them to behave.
Do you want them to appear only one at a time without allowing swipeing between them? If yes then add/insert a container layout(for example a simple FrameLayout) in your Activity on which you'll add the Fragments. I didn't worked with the SlidingMenu library but it should have a callback called when you click one of the items in the menu. In that callback you'll attach the proper fragment to the container layout(the FrameLayout) I mention earlier.
Do you want to show only one Fragment but you want to allow the user to swipe between them? If yes use a ViewPager in the activity layout and in the callback triggered by the SlidingMenu library's menu selection set the current page of the ViewPager with the setCurrentItem() method.
If you want something different then this provide more details.
Most tutorial are creating fragment with code, i just want to include
my 3 task into it
This, I don't quite understand. If you want to "include" your task fragments directly in your xml layout, you can but you'll be limited on what you can do with them(not to mention that all the fragments will be on one single screen) and I would avoid it. If you want something else provide more details.
I don't think it will work like that with Fragments, I was looking for a solution as well and ended up adding the fragments by hand.
I'm working on something similar like this, but for me there was also the case of opening WebViews to designated URL's. So the "above" screen would always update on any click.
To control the behaviour of this I created a MenuItemResource object, which basically holds the properties, like the ID of the icon, the name of the menu item and the URL.
public class MenuItemResource {
private int aValue;
private int aUrl;
private int aIconIdle;
private int aIconActive;
public MenuItemResource(int value, int url, int iconIdle, int iconActive) {
aValue = value;
aUrl = url;
aIconIdle = iconIdle;
aIconActive = iconActive;
}
}
The behaviour is handled by an OnItemClickListener which checks with a switch which values are in the MenuItemResource that is being clicked. For the WebView it's quite straightforward:
newFragment = new WebViewFragment();
final Bundle arguments = new Bundle();
arguments.putString(Constants.KEY_URL, getString(item.getUrl()));
newFragment.setArguments(arguments);
startFragment(newFragment, false);
// boolean is used to add the fragment to the backstack
The startFragment method just uses the FragmentManager and FragmentTransaction to replace the current Fragment. This works the same for other MenuItemResources that do start regular fragments.
newFragment = new Task1Fragment();
startFragment(newFragment, false);
I don't refer to the fragments in the MenuItemResource (yet), but it works pretty well for URLs and WebViews. The fragments are started based on the value in the MenuItemResource
I'm not sure how you would refer to the fragments like you did in the comments (Task1.java, etc), since you don't start them with Intents like Activities. Also I'm not sure why you would want to do this dynamically for Fragments (I can imagine this case being dynamic for WebViews though) as they need to be compiled anyway, so that's why my menu items are added by hand.

Categories

Resources