Android: ListView detail paging - android

Here's my setup: I have MainActivity which has the following code:
public class MainActivity extends FragmentActivity {
FragmentList listFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
listFragment = new FragmentList();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.list_container, listFragment);
fragmentTransaction.commit();
}
}
I then have FragmentList, which is a ListView fragment and FragmentDetail, which is the fragment displayed when selecting a particular ListView row.
Here's a snippet of the FragmentList code:
public class FragmentList extends Fragment {
private ListView list;
private FragmentDetail detailFragment;
private long detailId;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// ListView gets set via an adapter
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
detailId = id;
mPager = (ViewPager)getActivity().findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
mPager.setAdapter(mPagerAdapter);
final FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.list_container, detailFragment);
fragmentTransaction.commit();
}
});
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
detailFragment = new FragmentDetail();
Bundle mBundle = new Bundle();
mBundle.putLong("detailId", detailId);
detailFragment.setArguments(mBundle);
return detailFragment;
}
#Override
public int getCount() {
return 5;
}
}
}
And FragmentDetail:
public class FragmentDetail extends Fragment {
private long id;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.activity_view, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle bundle = getArguments();
id = bundle.getLong("detailId");
// Set views based on id
}
}
Here are my issues:
The line fragmentTransaction.replace(R.id.list_container, detailFragment); in FragmentList errors out saying that I cannot change ID of container. Why is that?
After I comment the line in issue #1 out, the detail fragment loads fine and lets me swipe. However, only one of the detail fragment pages contains any data; the rest are blank. How can I implement the following: say my ListView contains "iOS", "Android", "Windows" rows. When I click on "iOS", it brings up details fragment for iOS. When I swipe to the left, I want "Android" detail fragment to show up; then when I swipe again, "Windows" detail fragment, etc.
Thanks!

Related

Custom adapter for multiple fragments in one tab of ViewPager

I want to want to make ViewPager with each tab containing three fragments. FragmentPagerAdapter only works for one fragment, so I tried my best to make my own custom adapter extending PagerAdapter. Unfortunately, the code I wrote only displays these three Fragments in the first tab and after restarting the app all tabs are blank. I suspect that it has something to do with onSaveInstanceState, but I don't know how to make it properly. Also, I've read that I shouldn't add the fragments to FragmentTransaction in instantiateItem, but I don't know where else I could do it. Could you help me ?
TaskListPagerActivity:
public class TaskListPagerActivity extends AppCompatActivity implements BottomPanelFragment.OnBottomPanelSelectedListener {
private static final String TAG = "TaskListPagerActivity";
private ViewPager mViewPager;
FragmentStacker[] mStacker;
public static Intent newInstance(Context packageContext) {
Intent intent = new Intent(packageContext, TaskListPagerActivity.class);
return intent;
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_task_list_pager);
mStacker = new FragmentStacker[7];
mViewPager = (ViewPager) findViewById(R.id.activity_task_list_pager);
mViewPager.setAdapter(new TaskListPagerAdapter(this));
}
// Interface methods
private class TaskListPagerAdapter extends PagerAdapter {
private FragmentActivity mContext;
public TaskListPagerAdapter(FragmentActivity context) {
mContext = context;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment res;
FragmentManager fm = mContext.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if (mStacker[position] == null) {
mStacker[position] = new FragmentStacker();
ft.add(container.getId(), mStacker[position]);
} else {
ft.attach(mStacker[position]);
}
res = mStacker[position];
ft.commit();
return res;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
#Override
public int getCount() {
return 7;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return ((Fragment) object).getView()==view;
}
}}
FragmentStacker:
public class FragmentStacker extends Fragment {
Fragment[] fragments = createFragments();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.task_list_activity_fragment, container, false);
FragmentManager fm = getFragmentManager();
Fragment customDateFragment = fm.findFragmentById(R.id.custom_date_fragment_container);
Fragment taskListFragment = fm.findFragmentById(R.id.task_list_fragment_container);
Fragment bottomPanelFragment = fm.findFragmentById(R.id.bottom_panel_container);
FragmentTransaction fragmentTransaction = fm.beginTransaction();
if (customDateFragment == null) {
customDateFragment = fragments[0];
taskListFragment = fragments[1];
bottomPanelFragment = fragments[2];
fragmentTransaction.add(R.id.custom_date_fragment_container, customDateFragment);
fragmentTransaction.add(R.id.task_list_fragment_container, taskListFragment);
fragmentTransaction.add(R.id.bottom_panel_container, bottomPanelFragment);
fragmentTransaction.commit();
} else {
fragmentTransaction.attach(customDateFragment);
fragmentTransaction.attach(taskListFragment);
fragmentTransaction.attach(bottomPanelFragment);
}
return v;
}
private Fragment[] createFragments() {
return new Fragment[]{new CustomDateFragment(), new TaskListFragment(), new BottomPanelFragment()};
}}

Replacing a fragment with other fragment is giving me some issue

I am creating swipe screens using ViewPager where i have two fragments to show using swipes inside FragmentActivity .Please consider the following code :
Fragment_One.java
public class Fragment_One extends Fragment {
private Button btnNext;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_one,null);
btnNext = (Button) v.findViewById(R.id.btnNext);
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment = new Fragment_Two();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentOne,fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return v;
}
}
2.Fragment_Two.java
public class Fragment_Two extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_two,null);
}
}
3. PagerAdapter.java
public class PagerAdapter extends FragmentPagerAdapter {
List<Fragment> listFragments ;
public PagerAdapter(FragmentManager fm,List<Fragment> listFragments) {
super(fm);
this.listFragments = listFragments;
}
#Override
public Fragment getItem(int i) {
return listFragments.get(i);
}
#Override
public int getCount() {
return listFragments.size();
}
}
4.MainActivity.java
public class MainActivity extends FragmentActivity{
private List<Fragment> listFragments;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
Fragment_One fragment_one = new Fragment_One();
Fragment_Two fragment_two = new Fragment_Two();
listFragments = new ArrayList<>();
listFragments.add(fragment_one);
listFragments.add(fragment_two);
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(),listFragments);
viewPager.setAdapter(pagerAdapter);
}
}
The above mentioned code is working fine while swiping screens .But i click on next button ,fragment is replaced with another but is displayed on the same screen.I am not able to fix the issue.Screenshot is given below :
Next button should work in the same way as we swipe the screen .Please help me to fix the issue.
Wouldn't that be easier to use:
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
viewPager .setCurrentItem(viewPage.getCurrentItem() + 1);
});

Viewpager not working with fragment

My ViewPager is not working correctly. I don't know what's wrong with my code. I am facing some problems with my Fragments:
Basically, I have a Fragment named MyListFragment that has a list and on the click event of list item I move to the second Fragment named FlowersFragment that has a ViewPager with three items(Another three Fragments) in it. And i have a Button in my FlowersFragment and on click of that Button i move to the third screen named WelcomeFragment. now i have a problem :
If i go back to FlowersFragment from WelcomeFragment then it loses some Fragments from ViewPager after some research i got a solution like use childFragmentManager while creating adapter. That is good for my pager all Fragments are now showing correctly in my FlowersFragment Pager. But if I go back to MyListFragment and I click on second or third item of ListFragment its showing me exception with NO ACTIVITY.
Here is my FirstFragment named MyListFragment
public class MyListFragment extends Fragment{
private View view;
private FragmentManager fm;
private FragmentTransaction ft;
private ListView listviewPlaces;
private FloristAdapter adapter;
private ArrayList<FloristItems> items = new ArrayList<FloristItems>();
private FlowersFragment frag;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater = LayoutInflater.from(getActivity());
view = inflater.inflate(R.layout.fragment_list, container,false);
listviewPlaces = (ListView)view.findViewById(R.id.listviewPlaces);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
for (int i = 0; i < 10; i++) {
FloristItems florist = new FloristItems();
florist.away = "3 miles away";
florist.title = "Florist Flowers";
florist.price = "$45";
items.add(florist);
}
adapter = new FloristAdapter(getActivity().getApplicationContext(), items);
listviewPlaces.setAdapter(adapter);
listviewPlaces.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if(frag == null){
frag = new FlowersFragment();
}
handleFragments(frag);
}
});
}
private void handleFragments(Fragment fragment){
fm = getActivity().getSupportFragmentManager();
ft = fm.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.addToBackStack(null);
ft.commit();
}
}
Here is my FlowersFragment class that have view pager with containing three fragments:
public class FlowersFragment extends Fragment{
private View view;
private FragmentManager fm;
private FragmentTransaction ft;
private ViewPager pager;
private Button btnSendThatFlower;
private FlowerPagerAdapter pageAdapter;
private WelcomeFragment welcomeFrag;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater = LayoutInflater.from(getActivity());
view = inflater.inflate(R.layout.fragment_choose_flower_buyer, container,false);
pager = (ViewPager)view.findViewById(R.id.viewpager);
btnSendThatFlower = (Button)view.findViewById(R.id.btnSendThatFlower);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
pageAdapter = new FlowerPagerAdapter(getActivity().getSupportFragmentManager());
pager.setAdapter(pageAdapter);
btnSendThatFlower.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(welcomeFrag == null){
welcomeFrag = new WelcomeFragment();
}
handleFragments(welcomeFrag);
}
});
}
private void handleFragments(Fragment fragment){
fm = getActivity().getSupportFragmentManager();
ft = fm.beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.addToBackStack(null);
ft.commit();
} }
Here is my pager Adapter class:
public class FlowerPagerAdapter extends FragmentPagerAdapter{
private ArrayList<Fragment> pagerItems;
public FlowerPagerAdapter(FragmentManager fm) {
super(fm);
pagerItems = new ArrayList<Fragment>();
pagerItems.add(FlowerImage1.getInstance());
pagerItems.add(FlowerImage2.getInstance());
pagerItems.add(CustomFlowerFragment.getInstance());
}
#Override
public Fragment getItem(int num) {
if (num == 0) {
return new FlowerImage1();
}
else if(num == 1) {
return new FlowerImage2();
}
else{
return new CustomFlowerFragment.getInstance();
}
}
#Override
public int getCount() {
return pagerItems.size();
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
//super.restoreState(state, loader);
}}
FlowerImage1 FlowerImage1 CustomFlowerFragment are fragments with only imageview.
This is my last fragment WelcomeFragment
public class WelcomeFragment extends Fragment{
private View view;
private FragmentManager fm;
private FragmentTransaction ft;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater = LayoutInflater.from(getActivity());
view = inflater.inflate(R.layout.fragment_write_note_buyer, container,false);
return view;
}}
when i am pressing back press then its not showing fragments in viewpager but after swipe on view pager its showing only first or sometimes last pager fragment.
I have also faced same issue ended up adding following code inside fragment adapter.
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
//super.restoreState(state, loader);
}
I was also faced with the same problem, but i fixed it by extending "FragmentStatePagerAdapter" instead of FragmentPagerAdapter. for your case,it would be:
public class FlowerPagerAdapter extends FragmentStatePagerAdapter{
private ArrayList<Fragment> pagerItems;
public FlowerPagerAdapter(FragmentManager fm) {
super(fm);
pagerItems = new ArrayList<Fragment>();
pagerItems.add(FlowerImage1.getInstance());
pagerItems.add(FlowerImage2.getInstance());
pagerItems.add(CustomFlowerFragment.getInstance());
}
#Override
public Fragment getItem(int num) {
if (num == 0) {
return new FlowerImage1();
}
else if(num == 1) {
return new FlowerImage2();
}
else{
return new CustomFlowerFragment.getInstance();
}
}
#Override
public int getCount() {
return pagerItems.size();
}
}

Can't swipe to next item inside my detail activity after implementing viewpager

I am trying to swipe item(from listview) in my detail activity using viewpager.
I have 20 items in my listview (data parsed from json) Instead of swiping the next/previous item , It's only the same item that I swipe (20 times).
here is my DetailActivity.
public class DetailsActivity extends FragmentActivity {
Article feed;
int pos;
private DescAdapter adapter;
private ViewPager pager;
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.item_details);
pos = getIntent().getExtras().getInt("pos");
adapter = new DescAdapter(getSupportFragmentManager());
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
pager.setCurrentItem(pos);
}
public class DescAdapter extends FragmentStatePagerAdapter {
public DescAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 20;
}
public Fragment getItem(int position) {
return DetailFragment.newInstance(position);
}
}
And my detailFragment
public class DetailFragment extends Fragment {
static DetailFragment newInstance(int position) {
DetailFragment f = new DetailFragment();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.detail_fragment, container, false);
String displaytitle= getActivity().getIntent().getStringExtra("title");
TextView titleF = (TextView)view.findViewById(R.id.title);
titleF.setText(displaytitle);
...
return view;
}
What am I doing wrong?
You are not using the correct argument:
You send the argument "pos2" but you retrieve the argument "title".
#Override
public Fragment getItem(int position) {
DetailFragment frag = new DetailFragment();
Bundle bundle = new Bundle();
bundle.putInt("fPos",position);
frag.setArguments(bundle);
return frag;
}

Access ViewPager fragment views

I have a viewpager with 2 fragment pages inside it. Now i want to access the views (textview,buttons) from the first fragment page but everytime Iam getting Nullpointer exception
check out my code
Fragment i want to access its views:
public class ListPagerFragment extends Fragment
{
ListView listview;
TextView text;
private ViewPager pager;
public static ListPagerFragment newInstance(int message)
{
ListPagerFragment f = new ListPagerFragment();
// pass the text message received from main activity into a bundle to be
// delivered to the new fragment
Bundle bdl = new Bundle();
bdl.putInt("num", message);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.list_pager_fragment, container, false);
return v;
}
public void fillList(Nameslist list)
{
listview = (ListView) getView().findViewById(R.id.listView1);
if (listview == null)
System.out.println("listview null"); //this should not be null but
//it is thus the nullpointerexception
if (listview.getAdapter() == null)
{
MyListAdapter listAdapter = new MyListAdapter(getActivity(), R.layout.listview_item, list.getVenues());
listview.setAdapter(listAdapter);
}
else
{
((MyListAdapter) listview.getAdapter()).updateAdapter(list.getnames());
}
}
PagerAdapter code
public class MyPagerAdapter extends FragmentStatePagerAdapter
{
private int mCount = 1;
public MyPagerAdapter(FragmentManager fm)
{
super(fm);
// TODO Auto-generated constructor stub
}
#Override
public Fragment getItem(int position)
{
switch (position)
{
case 1:
return ResultsPagerFragment.newInstance(position);
}
return ListPagerFragment.newInstance(position);
}
#Override
public int getCount()
{
// TODO Auto-generated method stub
return mCount;
}
}
and main finally activity code
private ViewPager pager;
private MyPagerAdapter pagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
}
and later somewhere in the activity i have the code that should trigger the fillList from Fragment to do the job
Fragment frag = pagerAdapter.getItem(0); //this should give me the Fragment i want right?
((ListPagerFragment)frag).fillList(result);
What am I missing here?
Ok I found it seems like the problem was in my custom FragmentStatePagerAdapter
All I had to do is create the fragments when activity is created and put them into an ArrayList which it will be later passed to MyPagerAdapter
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
frags = new ArrayList<Fragment>();
frags.add(ListPagerFragment.newInstance(0));
frags.add(ResultsPagerFragment.newInstance(1));
pagerAdapter = new MyPagerAdapter(getSupportFragmentManager(),frags);
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
}
And then modify the MyPagerAdapter like so:
public class MyPagerAdapter extends FragmentStatePagerAdapter
{
private List<Fragment> fragments;
public MyPagerAdapter(FragmentManager fm, List<Fragment> frags)
{
super(fm);
this.fragments = frags;
}
#Override
public Fragment getItem(int position)
{
return fragments.get(position);
}
}
kind of silly isn't it? I don't understand the point but it worked
That's probably because you are trying to use the views from your Activity, before your ListPagerFragment.onCreateView() has inflated your xml layout. Move what's inside your onCreate() and some code of fillList() to onCreateView(), something like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.list_pager_fragment, container, false);
listview = (ListView) v.findViewById(R.id.listView1);
pagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
pager = (ViewPager) v.findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
return v;
}
After your fragments onCreateView() has inflated the view, you can try to fill it.
And don't forget to clear your view references and unregister your listview listener(if you set one) in onDestroyView() to avoid memory leaks, e.g.
#Override
public void onDestroyView() {
super.onDestroyView();
listview.setOnItemClickListener(null);
...
listview = null;
}
read about the fragment's lifecycle --> Fragment's Lifefycle

Categories

Resources