Activity for each row in database table - android

For an application which I am currently building in Java for Android I am looking for the following. I have a set with lets say 10 database records. For each row i want to show an activity (which is every time the same activity). The activity has some fields for each row to be updated.
Lets say for example you have a record set with contacts and now you want to loop through al 10 contacts and update the data.
Now I am not sure how this should work in android. Should I use fragments for this? How should i model this. Some pseudo code would help.
Since this is a custom app I am developing for ICS
Thanks very much

Create FragmentActivity with ViewPager.
ViewPager uses Adapter to display same fragments with different data.
For example, if you store in database images ids which you want to display, the code will look like this.
public class MyActivity extends FragmentActivity {
public static class MyFragment extends Fragment {
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final ImageView content = new ImageView(getActivity());
content.setImageResource(getArguments().getInt("img"));
return content;
}
}
private class MyPagerAdapter extends FragmentStatePagerAdapter {
private final ArrayList<Integer> imgs;
public AppTourPagerAdapter(final FragmentManager fm, final ArrayList<Integer> imgs) {
super(fm);
this.imgs = imgs;
}
#Override
public int getCount() {
return imgs.size();
}
#Override
public Fragment getItem(final int position) {
final MyFragment fragment = new MyFragment();
final Bundle args = new Bundle();
args.putInt("img", imgs.get(position));
fragment.setArguments(args);
return fragment;
}
}
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
final ViewPager pager = (ViewPager) findViewById(R.id.pager);
final ArrayList<Integer> imgIds = ... // get values from database
pager.setAdapter(new MyPagerAdapter(getSupportFragmentManager(), imgIds));
}
}

Use a viewpager with a viewpager adapter. then create a layout with a view pager, after that create a layout that will contain the items in the view pager you wish to flip through. In the adapter inflate the layout you wish to flip through. There are tons of examples online. Google it. You can copy paste 90% of what, you need to make it work.

Related

Need guidance in making efficient swipe views

New to android and recently learned swipe views a bit. In my app, it has 17 chapters and in each chapter, there will be 30 pages containing some text data, a user can swipe through. I need to use FragmentStatePagerAdapter to save memory but I need to know that do I need to make 510 Fragment objects, means 510 XML layout? I just need to change the text in each page, and I've seen many using switch statement like this
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FragmentOne();
case 1:
return new FragmentTwo();
default:
break;
}
return null;
}
Do I/Should I write 30 cases in each chapter? or is there a better way to do this? I've Googled and seen lots of Youtube videos but couldn't find the solution. I request everyone that if you're answering or commenting, do explain your codes cause I believe in learning, not in copy pasting.
Using FragmentStatePagerAdapter is right approach here. It will manage the fragment states based on the viepager offscreenLimit() you set.
In your case, you can have just one fragment and an arrayList of your text and given different text based on position.
Something like this..
List<String> yourList = new ArrayList<>();
#Override
public Fragment getItem(int position) {
return new YourFragment(yourList.get(position));
}
It's easy peasy man!
You need only one Fragment object, here's the code
public class FragmentChild extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
// INFLATE THE LAYOUT THAT EACH FRAGMENT OBJECT WILL HAVE, PUT IT IN A VIEW
View root = inflater.inflate(R.layout.couplets, container, false);
// RECEIVE THE BUNDLE DATA SENT (ARGUMENTS)
Bundle args = getArguments();
// CREATE AN ARRAY LIST OF STRINGS THAT WILL HOLD TEXT
ArrayList<String> someText = new ArrayList<>();
someText.add("one");
someText.add("two");
someText.add("three");
TextView txt = (TextView) root.findViewById(R.id.text_view);
txt.setText(someText.get(args.getInt("position")));
return root;
}
custom pager adapter
class MyFragmentAdapter extends FragmentStatePagerAdapter {
MyFragmentAdapter(FragmentManager fm) {super(fm);}
#Override
public Fragment getItem(int position) {
Bundle args = new Bundle();
args.putInt("position", position);
Fragment fragment = new FragmentChild();
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return 3;
}
}
And finally host activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chapter_one);
// FIND THE VIEWPAGER AND SET THE CUSTOM ADAPTER TO IT TO PROVIDE CHILD PAGES
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
MyFragmentAdapter adapter = new MyFragmentAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
}
}

ViewPager in NavigationDrawer

I've been trying something..unique..recently. Due to hierarchical levels of the app requiring multiple nav drawers, which isn't very good UX, I've been trying to add a ViewPager in the nav drawer which pages to show the list for the lower level in the hierarchy
Unfortunately, this doesn't seem to be working. Neither does it page, nor does it show an overscroll, indicating more fragments. Its not an Adapter problem, since all ViewPagers in the app are using the same adapter
Adapter
class AdapterClass extends FragmentStatePagerAdapter
{
List<Fragment> mFragments;
public AdapterClass(FragmentManager mFragManager, List<Fragment> mFragment)
{
super(mFragManager);
this.mFragments = mFragment;
}
#Override
public int getCount()
{
return mFragments.size();
}
#Override
public Fragment getItem(int position)
{
return mFragments.get(position);
}
}
Fragments (both fragments are same, save for the list text)
public class NavPagerFragMain extends SherlockFragment
{
View view;
ListView mList;
private ArrayList<String> mItems = new ArrayList<String>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.nav_pager_frag_main, container, false);
mList = (ListView)view.findViewById(R.id.nav_pager_frag_main);
mItems.add("Read");
mItems.add("Implement");
mItems.add("Design");
mItems.add("Download");
mItems.add("Connect");
mItems.add("Watch");
UserAdapter mAdapter = new UserAdapter(getActivity().getApplicationContext(), mItems);
mList.setAdapter(mAdapter);
return view;
}
Activity where I initialize and setup the ViewPager
mDrawer = (DrawerLayout)findViewById(R.id.app_drawer);
mDrawerItem = (ViewPager)findViewById(R.id.app_drawerpager);
List<Fragment> mInitFrags = new ArrayList<Fragment>();
mInitFrags.add(Fragment.instantiate(getApplicationContext(), NavPagerFragMain.class.getName()));
mInitFrags.add(Fragment.instantiate(getApplicationContext( ), NavPagerFragSub.class.getName()));
mAdapter = new AdapterClass(getSupportFragmentManager(), mInitFrags);
mDrawerItem.setAdapter(mAdapter);
mDrawerItem.setPageTransformer(true, new DepthPageTransformer());
Is your main Activity where you setup the ViewPager also a Fragment? If so, rather than pass the result of getSupportFragmentManager() to your adapter's constructor, pass it the result of the base fragment's getChildFragmentManager() call. In this scenario, you are effectively embedding Fragments within other fragments and the pager needs the child fragment manager to transition and deal with the children. Good luck!

Android Fragments in a ViewPager

I'm kinda confused about the whole Fragment-way-of-thinking. I've followed a tutorial on how to create a ViewPager with Fragments like the Google Play app.
I have TabFragment class like this one:
public class SwipeyTabFragment extends SherlockFragment {
#Override
public void onCreate(Bundle b) {
super.onCreate(b);
Log.e("FRAGMENT: ", "Hello World!");
}
public static Fragment newInstance(String title) {
SwipeyTabFragment f = new SwipeyTabFragment();
Bundle args = new Bundle();
args.putString("title", title);
f.setArguments(args);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_swipeytab, null);
final String title = getArguments().getString("title");
((TextView) root.findViewById(R.id.text)).setText(title);
return root;
}
}
I know that the onCreateView method initialize the layout and the controlls like Button, ListView and so on.
Over to my FragmentAdapter
private class SwipeyTabsPagerAdapter extends FragmentPagerAdapter implements SwipeyTabsAdapter {
private final Context mContext;
public SwipeyTabsPagerAdapter(Context context, FragmentManager fm) {
super(fm);
this.mContext = context;
}
#Override
public Fragment getItem(int position) {
return SwipeyTabFragment.newInstance(TITLES[position]);
}
#Override
public int getCount() {
return TITLES.length;
}
public TextView getTab(final int position, SwipeyTabs root) {
TextView view = (TextView) LayoutInflater.from(mContext).inflate(R.layout.swipey_tab_indicator, root, false);
view.setText(TITLES[position]);
view.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mViewPager.setCurrentItem(position);
}
});
return view;
}
}
This will just construct a new Tab based on a String-Array, which will set the text and the header of the Fragment.
So this is where I get confused. Say for instance that I want several fragments with different layout, and different ways of interacting when the user presses on Button, Picture or whatever. How can I do so?
Thanks.
All the 'user presses button' stuff is handled in the fragments, you can call back to the Activity of course when you need to (see here).
You have to create different fragment classes for different layouts, logic. etc. and return them to the ViewPager in getItem. You could have a FirstPageFragment and a SecondPageFragment, then return them (depending on the index) in getView. This only makes sense if those fragments have different functionalities of course.
Hope it's clear what I mean ;)
EDIT: as to your comment:
I don't know what exactly you want to do, but you have your SwipeyTabFragment already defined in it's own file. Take this then, modify it, give it another layout and other functionality, then call it OtherFragment or whatever. Let's say you want to have 2 different 'pages' in your App - the getCount() method in your adapter defines the amount of 'pages' in your ViewPager, so let's let it return two.
In the getItem() method, if position is 0, let it return your SwipeyFragment, else (position is 1) let it return your new OtherFragment. Now you have a ViewPager with 2 different Fragments that can serve totally different purposes.

Updating fragments from Activity in a ViewPager

I'm new to Android developing and I would really appreciate some help here.
I'm using a fragment that contains a TextView and I'm using 5 instances of the same MyFragment class.
In the activity, i got a button and a ViewPager, and I need the button to update all the fragment instances content, whenever its clicked.
Here's the Activity
public class MainActivity extends FragmentActivity {
final static String[] CONTENT = {"a", "b"};
ViewPager pager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<MyFragment> fragments = new Vector<MyFragment>();
for(int i = 0; i < 5; i++){
MyFragment fragment = new MyFragment(CONTENT);
fragments.add(fragment);
}
PagerAdapter adapter = new PagerAdapter(this.getSupportFragmentManager(), fragments);
pager = (ViewPager) findViewById(R.id.viewpager);
pager.setAdapter(adapter);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//method that isn't working
PagerAdapter adapter = (PagerAdapter)pager.getAdapter();
for(int i = 0; i < 5; i++){
MyFragment fragment = (MyFragment) adapter.getItem(i);
fragment.textView.setText(fragment.content[1]);
}
}
});
}
}
The Fragment
public class MyFragment extends Fragment{
String[] content;
TextView textView;
public MyFragment(String[] content) {
this.content = content;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_content, container, false);
textView = (TextView) view.findViewById(R.id.textView1);
textView.setText(content[0]);
return view;
}
}
And the FragmentPagerAdapter
public class PagerAdapter extends FragmentPagerAdapter{
List<MyFragment> fragments;
public PagerAdapter(FragmentManager fm, List<MyFragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int arg0) {
return fragments.get(arg0);
}
#Override
public int getCount() {
return fragments.size();
}
}
The OnClick method gives me a NullPointerException whenever i try to access a fragment from the adapter which is less than adapter.getCurrentItem() - 1, or more than adapter.getCurrentItem() + 1.
Any idea on how to update all the fragments at the same time?
Thanks in advance.
The easiest way to update those fragments is to use your code and set the number of fragments that the ViewPager holds in memory to the number of total fragments - 1(so all fragments are valid no matter at what page you are). In your case:
pager.setOffscreenPageLimit(4); // you have 5 elements
You can still use the method from my comment with the method onPageScrollStateChanged(so the update will start the moment the user starts swiping) to see when the user is starting to swipe the pager and update the fragments to the left and right of the currently visible fragment, but this will be a bit difficult to get right so I recommend to go with the first option.
Some points regarding your code containing fragments:
If you nest the fragment class make it static so you don't tie it to the activity object.
Don't create a constructor for a Fragment besides the default one. If the framework needs to recreate the fragment it will call the default constructor and if it is not available it will throw an exception. For example, try to change the orientation of the phone/emulator and see what happens(this is one of the cases when Android will recreate the fragments). Last, use a custom name for the ViewPager's adapter, you use PagerAdapter which is the name of the super class of FragmentViewPager and it's very confusing for someone reading your code.
If you need to pass data to the Fragment you could use a creation method like the one below:
public static MyFragment newInstance(String text) {
MyFragment f = new MyFragment();
Bundle b = new Bundle();
b.putString("content", text);
f.setArguments(b);
return f;
}
The text will be available in MyFragment by using getArguments().getString("content");

How to refresh current view in ViewPager

I am using ViewPager with views V1, V2, V3 ..... I am trying to set visibility of a LinearLayout used in each view, by clicking on a button. Through this code it apply the change on the next view instead of the current view. e.g. I am on V5. When I click it hides/show the object on V6. If I am going backwards from V6 to V5, then it applies the change on V4.
Here is the code:
public class FragmentStatePagerSupport extends FragmentActivity {
static final int NUM_ITEMS = 10;
MyAdapter mAdapter;
ViewPager mPager;
static int mNum;
private Button btn_zoom;
static LinearLayout LL_Head;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_pager);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(5);
btn_zoom = (Button)findViewById(R.id.btn_zoom);
btn_zoom.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
if (LL_Head.getVisibility() == View.VISIBLE) {
LL_Head.setVisibility(View.GONE);
}else{
LL_Head.setVisibility(View.VISIBLE);
}
}
});
.
.
.
}
public static class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
}
public static class ArrayListFragment extends ListFragment {
static ArrayListFragment newInstance(int num) {
ArrayListFragment f = new ArrayListFragment();
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.sura_vpager, container, false);
TextView tv1=(TextView) v.findViewById(R.id.txtHead);
tv1.setText("Fragment #" + mNum);
LL_Head = (LinearLayout)v.findViewById(R.id.LL_Head);
return v;
}
Please advise
Thanks
In order to make a fluent experience the ViewPager not only loads the view you are currently looking at, but also the adjacent views. That means, that if you are scrolling from position 0 to position 1, what actually happens is that position 2 is loaded, so it will be ready when you scroll on. This is why the change is applied to the "next" view, rather than the current one (if you scroll from view 2 to 1, then view 0 is created).
Since you are setting the static LinearLayout in OnCreate, then it's only the last view to be created that is changed - and this will only ever be the one you are looking at, if you have scrolled to the end of the pager. Instead you should keep track of which fragment the user is looking at (ViewPager.setOnPageChangeListener()) and cache the fragment in your adapter. You then know which fragment position you want, and when you ask for it, you will just return the one you previously created (don't create a new one, then it won't work :)).
Or, the tl;dr version:
LL_Head is almost always set to be the next fragment, not the current one. Don't set it statically. Cache it in your PagerAdapter and reget it when you need it.
Edit:
Alternatively you may want to have the fragments listen to an event of sorts, which tells them whether they should show or hide the layout in question. Otherwise it will only be the current fragment that is affected by this, rather than all fragments.
The numbering in Java starts from 0. Thus when you want to set the 5th item, you have to call mPager.setCurrentItem(4);
Hope this helps!

Categories

Resources