My app is an icon view like app drawer
Each page has 12 icons, if more than 12 icons, other icons will display in next page.
I use viewpager and gridview to implement this interface, Each fragment of viewpager has a gridview to display items.
In FragmentActivity, I can get the current page index by adding OnPageChangeListener to viewpager.
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
But I cannot get the index in fragment
public class MyFragment extends Fragment {
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
public static final MyFragment newInstance(String message)
{
MyFragment f = new MyFragment();
Bundle bdl = new Bundle(1);
bdl.putString(EXTRA_MESSAGE, message);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String message = getArguments().getString(EXTRA_MESSAGE);
View v = inflater.inflate(R.layout.fragment, container, false);
//suppose the list has 15 items now
ArrayList list=new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
list.add(8);
list.add(9);
list.add(10);
list.add(11);
list.add(12);
list.add(13);
list.add(14);
list.add(15);
GridView gridview = (GridView) v.findViewById(R.id.gridview);
int currentIndex=??? //how to get index?
if(currentIndex==0){
gridview.setAdapter(new GridViewAdapter(list.subList(0,12));
} else if (currentIndex==1) {
gridview.setAdapter(new GridViewAdapter(list.subList(12,15));
}
return v;
}
}
The fragment in different page should display different sub list of items, how get index in fragment?
There is a method named getItem(int position) you will have to override when you create your FragmentPagerAdapter. You can pass the index there.
Since you have this:
public static final MyFragment newInstance(String message)
{
MyFragment f = new MyFragment();
Bundle bdl = new Bundle(1);
bdl.putString(EXTRA_MESSAGE, message);
f.setArguments(bdl);
return f;
}
You can put your index in your bdl and get it later in your onCreate()
You should get reference to viewPager in your fragment and just read it.
viewPager.getCurrentItem()
http://developer.android.com/reference/android/support/v4/view/ViewPager.html#getCurrentItem%28%29
Related
I have a tab that holds a view pager with 5 fragments in it.
When onPageSelected is called then I tell the current fragment to animate up using
((ItemFragment) pagerAdapter.getItem(position)).animateUp();
and Inside the fragment
public void animateUp(){
if(linearLayout != null){
linearLayout.animate().translationYBy(-75));
}
}
Everything seems to work fine until I rotate the device. The fragments are shown and I can move them but the animateUp() method doesn't do anything. It seems like the viewpager doesn't have a reference to the fragments being shown.
Edit: onCreate is empty, here is onCreateView
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_explore_tab, container, false);
pager = (MultiViewPager)rootView.findViewById(R.id.pager);
List<Fragment> fragmentsList = new ArrayList<>();
for(int i = 0; i < header.length; i++){
ItemFragment fragment = new ItemFragment();
Bundle bundle = new Bundle();
bundle.putInt(ItemFragment.IMAGE_KEY, header[i]);
fragment.setArguments(bundle);
fragmentsList.add(fragment);
}
pager.addOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
((ItemFragment) pagerAdapter.getItem(position)).animateUp();
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
pagerAdapter = new BaseFragmentPagerAdapter(getChildFragmentManager(), fragmentsList);
pager.setAdapter(pagerAdapter);
return rootView;
}
if(linearLayout != null){ *your listener change to null when you rotate device*
linearLayout.animate().translationYBy(-75)); }
You must subscribe listener once more. Try to do this in onResume
I am using android PagerStrip Slidding tab. I have two fragments. In the first fragment I have a listview.I want to navigate to the second fragment wen i click on the listview item in the first fragment . How do i do this? Thanks.
Here is the OnClick Listener in Fragment1
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragmentcontainer,Fragment2.newInstance());
transaction.addToBackStack(null);
}
});
//Here is my Fragment 2 which i want to navigate to
public class Fragment2 extends Fragment {
private static final String ARG_POSITION = "position";
public static final String TAG = Fragment2.class
.getSimpleName();
#InjectView(R.id.textView)
TextView textView;
private int position;
public static Fragment2 newInstance(int position) {
Fragment2 f = new Fragment2();
Bundle b = new Bundle();
b.putInt(ARG_POSITION, position);
f.setArguments(b);
return f;
}
public static Fragment2 newInstance(){
Fragment2 f = new Fragment2();
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
position = getArguments().getInt(ARG_POSITION);
//setContentView(R.layout.activity_maps);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_card,container,false);
ButterKnife.inject(this, rootView);
ViewCompat.setElevation(rootView, 50);
textView.setText("CARD "+position);
return rootView;
}
}
I have figured out how to do this.
1. In the MainActivity your might already have
ViewPager pager;
and in your Oncreate method you also have
......
pager.setAdapter(adapter);
Now create the method below in the MainActivity below.ie(The Activity which controls all your fragments etc)
public void setCurrentItem (int position, boolean smoothScroll) {
pager.setCurrentItem(item,true);
}
Now Lets assume your fragment1 has a listview or button.And you want to navigate to fragment2 by onClick.
This is what you need to do
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,int position, long arg3) {
((MainActivity)getActivity()).setCurrentItem (1, true);
}
});
//Remeber int position is the position of the fragment you want to navigate to in your Adapter
I've been trying to get an id from a listview-onclicklistener to three tabbed fragments. The user firstly clicks in myTicketsFragmentand then goes to the detail page which contains 3 swipeable tabs. These views are 'hosted' by one individual activity named TicketActivity. So currently I've succesfully passed data from the fragment to TicketActivity but I cannot go further than that. Been searching for 2 hours now and still no results..
Here's my code:
myTicketsFragment: passing the data in setOnItemClickListener to tab activity
public void onItemClick(AdapterView<?> parentView,
View childView, int position, long id) {
Bundle bundle = new Bundle();
bundle.putInt("ticketId", myTickets.get(position).getId());
Intent ticketDetail = new Intent(getActivity(), TicketActivity.class);
ticketDetail.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
ticketDetail.putExtras(bundle);
startActivity(ticketDetail);
}
TicketActivity: receiving data and passing it through to the 3 tabs
private ViewPager viewPager;
private TicketTabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Info", "Intern", "Extern" };
public TicketInfoFragment ticketInfoFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs);
// Receive data
Bundle bundle = getIntent().getExtras();
int ticketId = bundle.getInt("ticketId");
// Pass data to fragments
// ...
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TicketTabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
Example of a tab fragment
public class TicketInfoFragment extends Fragment {
TicketFull ticket = new TicketFull();
private DatabaseHelper db;
int ticketId;
String androidId;
String authCode;
String platform_url;
int uId;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
db = new DatabaseHelper(getActivity());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_ticket_info, container, false);
return rootView;
}
}
I would be pleased if anyone could help me out
Thanks in advance
2 quick ways:
use an static method in your activity to retrieve current ticket id
Design and implement an interface and register the fragments as listeners from the activity
First option, In your activity:
private static int ticketId;
public static int getCurrentTicketId(){
return ticketId;
}
and in your fragment you can do:
TickerActivity.getCurrentTicketId();
Second option, Use an interface:
public interface TicketListener{
public void onTicketChanged(int newTicket);
}
and in your activity add:
public List<TicketListener> listeners = new ArrayList<TicketListener>();
public void addListener(TicketListener listener){
listeners.add(listener);
}
and register every fragment as a new listener
YourFragment frag = new YourFragment();
addListener(frag);
and finally when you want to notify the key to the listeners iterate over the list:
for(TicketListener listener : listeners){
listener.onTicketChanged(ticket);
}
You can do in two different ways. The more simple is in your Activity container has to provider a getter for the data that you want to access from the Fragments, so in your fragments has to access to this getter via getActivity to get a reference to the father and the invoke the get method, I mean:
In TicketActivity:
private int ticketId;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
// Receive data
Bundle bundle = getIntent().getExtras();
ticketId = bundle.getInt("ticketId");
...
}
public int getTicketId() {
return ticketId;
}
And in your fragments:
((TicketActivity)getActivity()).getTicketId();
Or a more elegant way, is passing the Bundle via arguments when you initialize your fragments. You will have to do this inside your TicketTabsPagerAdapter class. I mean something like that:
TicketInfoFragment f = new TicketInfoFragment();
f.setArguments(bundle);
To do this last method is better use the Singleton pattern. You can follow the next link: http://developer.android.com/reference/android/app/Fragment.html
public static class DetailsFragment extends Fragment {
/**
* Create a new instance of DetailsFragment, initialized to
* show the text at 'index'.
*/
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
// Supply index input as an argument.
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f;
}
public int getShownIndex() {
return getArguments().getInt("index", 0);
}
it is very simple. When you will pass a bundle from ActivityA to other ActivityB(with bundle). it will be received by the ActivityB class instead of fragment.
It's simple to implement:
in onResume method of ActivityB ==> receive the bundle and passes attach it to your required fragment. check my code to pass from onresume to Framgent class
String tag = Constants.TAG_Search;
Fragment fragment;
fragment = fragmentManager.findFragmentByTag(tag);
fragmentTransaction.remove(fragment);
Search searchFragment = new Search();
searchFragment.setArguments(Globals.bd);
fragmentTransaction.add(R.id.tab2, searchFragment, tag);
Hope it will help
I have 2 fragments (tabs) that share some data. When one changes the data, I'd like to have that reflected on the other tab. I researched this on stackOverflow and I think the relevant answer has to do with a .notifyDataSetChanged() call, but I can't make it work. Here's the relevant code...
public class EnterCourseData extends FragmentActivity implements ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Pars", "Handicaps" };
private int courseNumber, teeNumber;
private Tee tee;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_enter_tees);
// Initilization
Intent mIntent = getIntent();
courseNumber = mIntent.getIntExtra("courseNumber",0);
Course course = Global.getCourse(courseNumber);
teeNumber = mIntent.getIntExtra("teeNumber",0);
tee = course.getTee(teeNumber);
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager(), courseNumber, teeNumber);
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
/**
* on swiping the viewpager make respective tab selected
* */
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
and further down, here is the onClick method that necessitates the refresh...
public void savePars(View view){
tee.setSlope(Integer.parseInt(((EditText) findViewById(R.id.enter_tee_slope)).getText().toString()));
tee.setRating(Double.parseDouble(((EditText) findViewById(R.id.enter_tee_rating)).getText().toString()));
mAdapter.notifyDataSetChanged();
}
Here is the TabsPagerAdapter...
public class TabsPagerAdapter extends FragmentPagerAdapter {
int courseNumber, teeNumber;
public TabsPagerAdapter(FragmentManager fm, int courseNumber, int teeNumber) {
super(fm);
this.courseNumber = courseNumber;
this.teeNumber = teeNumber;
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Par Entry activity
Fragment parFragment = new ParFragment();
Bundle args = new Bundle();
args.putInt(ParFragment.ARG_COURSE_NUMBER, courseNumber);
args.putInt(ParFragment.ARG_TEE_NUMBER, teeNumber);
parFragment.setArguments(args);
return parFragment;
case 1:
// Handicap Entry fragment activity
Fragment hcpFragment = new HandicapFragment();
args = new Bundle();
args.putInt(HandicapFragment.ARG_COURSE_NUMBER, courseNumber);
args.putInt(HandicapFragment.ARG_TEE_NUMBER, teeNumber);
hcpFragment.setArguments(args);
return hcpFragment;
}
return null;
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 2;
}
}
Here is one Fragment...
public class ParFragment extends Fragment {
public static final String ARG_COURSE_NUMBER = "courseNumber", ARG_TEE_NUMBER = "teeNumber";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_par, container, false);
Bundle args = getArguments();
Course course = Global.getCourse(args.getInt(ARG_COURSE_NUMBER));
((TextView) rootView.findViewById(R.id.display_course_name)).setText(course.getName());
Tee tee = course.getTee(args.getInt(ARG_TEE_NUMBER));
((TextView) rootView.findViewById(R.id.display_tee_name)).setText(tee.getTeeName());
((TextView) rootView.findViewById(R.id.enter_tee_slope)).setText(Integer.toString(tee.getSlope()));
((TextView) rootView.findViewById(R.id.enter_tee_rating)).setText(Double.toString(tee.getRating()));
return rootView;
}
}
And here is the other...
public class HandicapFragment extends Fragment {
public static final String ARG_COURSE_NUMBER = "courseNumber", ARG_TEE_NUMBER = "teeNumber";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_handicap, container, false);
Bundle args = getArguments();
Course course = Global.getCourse(args.getInt(ARG_COURSE_NUMBER));
((TextView) rootView.findViewById(R.id.display_course_name)).setText(course.getName());
Tee tee = course.getTee(args.getInt(ARG_TEE_NUMBER));
((TextView) rootView.findViewById(R.id.display_tee_name)).setText(tee.getTeeName());
((TextView) rootView.findViewById(R.id.enter_tee_slope)).setText(Integer.toString(tee.getSlope()));
((TextView) rootView.findViewById(R.id.enter_tee_rating)).setText(Double.toString(tee.getRating()));
return rootView;
}
}
When the button is clicked, I want to save the values and I want these values to show up on the other fragment.
Help a noob out.
Thanks
You need to communicate between fragments, but a fragment cannot directly communicate with other fragment, all the communication should be done through the activity which holds these fragments.
The steps to follow are :
Define an Interface in the fragment where you have implemented the onClickListener (let it be Fragment A)
Implement the Interface in the activity which holds these fragments
In the method overridden, retrieve the fragment instance from the viewpager adapter and deliver a message to Fragment B by calling it's public methods.
refer this answer to retrieve fragment instance from adapter
For more details about Communicating with Other Fragments, refer here
So there is a trick: just let the fragments have the object reference of one another and call the other's function to load data when you handle the onClickListener of the button.
E.g:
protected void onClickListener(View view) {
if (view == myButton) {
// Do other stuffs here
fragment1.reloadData();
}
}
P/S : I re-post this as answer to have the code formatter.
I am developing application using viewpager with fragment.In my application i have a items which i showing in List.After that when i click i have calling SherlockFragmentActivity which calling ViewPager with adapter.Now the problem is getItem in FragmentPagerAdapter give multiple position at a single time.Also when i flip backword then also giveing wrong position.Here is my code
ViewPager Code:-
private void initialisePaging() {
//Adapter Context;
this.mPagerAdapter = new MyPagerAdapter(
super.getSupportFragmentManager(), getApplicationContext(),
title, link, description);
ViewPager pager = (ViewPager) super.findViewById(R.id.viewpager);
pager.setAdapter(this.mPagerAdapter);
//Take position from ListView & set postion .
pager.setCurrentItem(post_position);
}
My Adapter Class which responsible for set fragment:-
Problem:- The problem is getItem Calling 3 time & suppose i click on 4 item its giving me 3,4,5 number.
public MyPagerAdapter(FragmentManager fm, Context cont,
ArrayList<String> title, ArrayList<String> link,
ArrayList<String> description) {
super(fm);
this.context = cont;
this.key_desc = description;
this.key_link = link;
this.key_title = title;
viewPagerApplication = (RssItem) cont;
}
#Override
public Fragment getItem(int position) {
return Fragment0.newInstance(position, this.context, key_title,
key_link, key_desc);
}
#Override
public int getCount() {
return key_title.size();
}
My Fragment Class:-
Problem:-Here if i show postion in textview its correct position but if i want take position in logcat for further parsing its giving me again 4,3,5 number which is also diffrent from getItem();
public static Fragment0 newInstance(int num,Context cont, ArrayList<String> key_title, ArrayList<String> key_link, ArrayList<String> key_desc) {
context=cont;
Fragment0 f = new Fragment0();
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
};
public int getShownIndex() {
return getArguments().getInt("num", 0);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.newsdetailfragment_screen, container, false);
tv = v.findViewById(R.id.headingtextview_id);
((TextView)tv).setText(String.valueOf(getShownIndex()));
((TextView)tv).setTextColor(Color.BLACK);
((TextView)tv).setTextSize(20);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
Now kindly let me know where i am wrong & how can i get only one exact position for further process.
Inside of getItem(), the position parameter is the position that is in need of rendering. It is NOT the position of the currently focused item that the user would see. The pages to the left and right of the currently displayed view need to be pre rendered in memory so that the animations to those screens will be smooth. To get the item at current position use:
pager.getCurrentItem();
If you need an actual position of the page you can implement onPageChangeListener
pager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
}
position in onPageSelected will give an accurate current position of the page.