I'm wondering how can I work with a listfragment, and at the same time, using an static linearlayout with 4 filter buttons at the top of the list. Here is the problem:
First of all, I use an Action Bar + Tab Navigation from ActionBarSherlock :
QuestList extends FragmentMapActivity implements ActionBar.TabListener
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getTabs();
}
private void getTabs() {
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tab1 = getSupportActionBar().newTab();
tab1.setText("Geo");
tab1.setTabListener(this);
getSupportActionBar().addTab(tab1);
ActionBar.Tab tab2 = getSupportActionBar().newTab();
tab2.setText("No Geo");
tab2.setTabListener(this);
getSupportActionBar().addTab(tab2);
}
...
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (tab.getText().toString().compareTo("Geo") == 0) {
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, Map.getInstance()).commit();
}
else {
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, List.newInstance(0)).commit();
}
}
I got some problems with the MapView, but I finally fixed all of them. Now the problem is that I want something like this:
Static LinearLayout + ListFragment
List extends ListFragment
...
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initializations();
getQuests();
if (gigHash.isEmpty()) {
TextView eList = new TextView(getActivity());
eList.setText(R.string.no_loc_gig_no_items);
eList.setWidth(Gravity.CENTER);
}
else {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
mAdapter = new NoLocGigAdapter(getActivity(),R.layout.gig_noloc_row_land,gigList);
}
else {
mAdapter = new NoLocGigAdapter(getActivity(),R.layout.gig_noloc_row,gigList);
}
setListAdapter(mAdapter);
}
}
...
So I'm using my own adapter and I get all my items from a service.
The problem is, doing the transaction, I can only use a fragment, and I have to show the items dinamically with my own ArrayAdapter, so I don't know how to include a part of static code into that view...
Any suggestion? I think that handle with fragments it's a little weird!
PS: At first, I thought that I could call a fragment, and this, calling a static xml within the linearlayout and a ListFragment inside, but I think I can't do this, right?
Related
I am a newbie in android programming.I added three fragments in my main activity as follows.Each fragment contains a list view.The items in list view is added from json output.Now i need to call same json request from each fragments.Can i set listview items from my main activity ? and avoid 2 json requests ?
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MainActivity extends ActionBarActivity implements
android.support.v7.app.ActionBar.TabListener {
ViewPager viewPager;
// Using appcompat action bar
private android.support.v7.app.ActionBar actionBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager);
FragmentManager fragmnetManager = getSupportFragmentManager();
viewPager.setAdapter(new MyAdapter(fragmnetManager));
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
#Override
public void onPageSelected(int pos)
{
actionBar.setSelectedNavigationItem(pos);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
// Getting actionbar
actionBar = getSupportActionBar();
// Setting navigation mode to actionbar
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Now adding a new tab to action bar and setting title, icon and
// implementing listener
android.support.v7.app.ActionBar.Tab tab1 = actionBar.newTab();
tab1.setText("TAB1");
// tab1.setIcon(R.drawable.ic_launcher);
tab1.setTabListener(this);
android.support.v7.app.ActionBar.Tab tab2 = actionBar.newTab();
tab2.setText("TAB2");
tab2.setTabListener(this);
android.support.v7.app.ActionBar.Tab tab3 = actionBar.newTab();
tab3.setText("TAB3");
tab3.setTabListener(this);
// Now finally adding all tabs to actionbar
actionBar.addTab(tab1);
actionBar.addTab(tab2);
actionBar.addTab(tab3);
}
#Override
public void onTabReselected(android.support.v7.app.ActionBar.Tab arg0,
FragmentTransaction arg1)
{
}
#Override
public void onTabSelected(android.support.v7.app.ActionBar.Tab tab,
FragmentTransaction arg1)
{
// Setting current position of tab to view pager
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(android.support.v7.app.ActionBar.Tab arg0,
FragmentTransaction arg1) {
}
}
// My adapter i.e. custom adapter for displaying fragments over view pager
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
// Getting fragments according to selected position
Fragment fragment = null;
if (i == 0) {
fragment = new FragmentA();
}
if (i == 1) {
fragment = new FragmentB();
}
if (i == 2) {
fragment = new FragmentC();
}
// and finally returning fragments
return fragment;
}
#Override
public int getCount() {
// Returning no. of counts of fragments
return 3;
}
}
You can also try this if you don't want to implement interface (because you are having only three fragment) - To avoid two json request on different fragment, just send one json request and after getting data in two different list, you can call a method in second fragment to set listview's data in second fragment from first fragment.
Let's say you got two list(firstList, secondList) of data from jsonResponse then set first arraylist in currentFragment and to set data in second fragment try like below method-
Define fragment's instances in Activity like -
FirstFragment firstFragment;
SecondFragment secondFragment;
initialize them where you add fragment like -
secondFragment = new SecondFragment();
in SecondFragment -
public void updateListView(ArrayList list){
secondArrayList.addAll(list);
secondAdapter = new Adapter(superContext, R.layout.single_item, secondArrayList);
listView.setAdapter(secondAdapter);
}
call this method from activity -
secondFragment.updateListView(secondList);
This solution is better if you have number of fragments small.
Yes you can. Create a interface in your mainActivity as follows
public interface Communicator{
void onDataLoaded(<Whatever data you want to send to fragment>)
}
now create an instance of this interface in your main activity
Communicator mCommunicator;
In your getItem method, for which fragment you want to send data to initialize the communicator as follows
mCommunicator=(Communicator)fragment;
Then in your main activity once your JSON is loaded just call mCommunicator.onDataLoaded();
Make sure your fragment implements this interface. Once you implement it you will get data there and you can update your listview.
I am developing an app which is using ActionBar.NAVIGATION_MODE_TABS and a separate FragmentPagerAdapter class in order to swipe through 5 different screens. On these screens there are buttons you can press to load a new activity, and then go back to the MainActivity when done. My problem is, every time you go back and reload the MainActivity it defaults back to the first tab (0).
I have tried many different solutions to try and get the previously selected tab to load when the activity is reloaded including SharedPreferences, saving instance state and trying to force the FragmentPagerAdapter class to load a certain fragment when called - but something keeps overriding it and it always goes back to the first tab (0) without fail. I would be really grateful for any possible solutions to this.
Code as follows:
public class MainActivity extends FragmentActivity implements TabListener {
ActionBar tabBar;
ViewPager viewPager;
#Override
protected void onCreate(Bundle currenttab) {
super.onCreate(currenttab);
setContentView(R.layout.activity_main);
// Sets up view pager
viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setCurrentItem(0);
viewPager.setAdapter(new MainAdapter(getSupportFragmentManager()));
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int currenttab) {
tabBar.setSelectedNavigationItem(currenttab);
}
#Override
public void onPageScrolled(int currenttab, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int currenttab) {
}
});
// Adds tabs to action bar
tabBar = getActionBar();
tabBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tab1 = tabBar.newTab();
tab1.setIcon(R.drawable.action);
tab1.setTabListener(this);
ActionBar.Tab tab2 = tabBar.newTab();
tab2.setIcon(R.drawable.jobs);
tab2.setTabListener(this);
ActionBar.Tab tab3 = tabBar.newTab();
tab3.setIcon(R.drawable.historic);
tab3.setTabListener(this);
ActionBar.Tab tab4 = tabBar.newTab();
tab4.setIcon(R.drawable.breeds);
tab4.setTabListener(this);
ActionBar.Tab tab5 = tabBar.newTab();
tab5.setIcon(R.drawable.special);
tab5.setTabListener(this);
tabBar.addTab(tab1);
tabBar.addTab(tab2);
tabBar.addTab(tab3);
tabBar.addTab(tab4);
tabBar.addTab(tab5);
}
// Action bar methods
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
// Class to deal with swipe function
class MainAdapter extends FragmentPagerAdapter {
public MainAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int currenttab) {
// TODO Auto-generated method stub
Fragment fragment = null;
if (currenttab == 0) {
fragment = new FragmentAction();
}
if (currenttab == 1) {
fragment = new FragmentJobs();
}
if (currenttab == 2) {
fragment = new FragmentHistory();
}
if (currenttab == 3) {
fragment = new FragmentBreeds();
}
if (currenttab == 4) {
fragment = new FragmentSpecial();
}
return fragment;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return 5;
}
}
I managed to resolve this by making my back buttons behavior mimic the built in behavior of calling onBackPressed();. The problem was going back using my previous code was creating a new instance of my MainActivity thus defaulting it to the first tab.
I am trying to understand Android fragments and navigation, but there is something I just don't know how to do. I have created an app, with a MainActivity containing a viewPager :
public class MainActivity extends FragmentActivity implements TabListener
{
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
private String[] tabNames = {"Tab 1", "Tab 2", "Tab 3"};
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for(int i = 0 ; i < tabNames.length ; i++)
actionBar.addTab(actionBar.newTab().setText(tabNames[i]).setTabListener(this));
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {}
}
Here is TabsPagerAdapter :
public class TabsPagerAdapter extends FragmentPagerAdapter
{
public TabsPagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int index)
{
if(index == 0) return new FirstFragment();
else if(index == 1) return new SecondFragment();
else return new ThirdFragment();
}
#Override
public int getCount()
{
return 3;
}
}
And my FirstFragment is a list so it extends ListFragment. Here is what it looks like :
Now I want to go to another view if I click an item. Before I used to do it like this in apps without action bar and tabs :
Intent i = new Intent(this.getActivity().getApplicationContext(), MyNewActivity.class);
startActivity(i);
But now when I do this it doesn't display the action bar on top of the screen anymore, and I also want to keep the navigation state on this tab, if I go to another tab and then come back. What should I do?
Thanks for your help.
It is better to let each individual fragment manage its own menu items (actionbar) so you have to call setHasMenuOptions(true) in each fragment that you want to have menu options in. Get a reference to the actionbar in onActivityCreated() and configure your actionbar how you want it there. You will also have to override the oncreateoptionsmenu and onOptionsItemSelected in the fragment to handle menu item clicks.
Also using the view pager and tabs you want to make each tab a fragment. I don't know about making each tab an activity, and I don't even think that is possible, and if you are doing that then that is your problem. I don't see that from your code, and that is good.
Each tab needs to be a Fragment, so convert all of your activities into fragments and then use the supportFragmentManager to dynamically add and replace fragments to your framelayout resource, or override getItem and return the correct fragment as needed.
So recently I needed to implement action bar tabs that would swap out the current fragment with a new fragment. Despite hours of intensive searching I was unable to find a clear solution, so I thought I would present how I solved the problem here. Two of the fragments contained list views, which turned out to be a major complicating factor.
First create an Activity to which you want to attach the fragments. In the XML file for that Activity add a linear layout like so:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".WoodenSideProject" >
<LinearLayout
android:id="#+id/fragment_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
Do not add anything else to the XML file. Not even the tab host that is preloaded with Eclipse.
Next create your fragments. First build the UI for your fragment how you want it using the fragment's XML file. I will show how to create a fragment with a List View:
public class Fragment1Name extends Fragment
{
public static String TAG="DirectionsFragment";
private String[] list_items = {"Put the list of Strings you want here"};
ListView lView1;
/*#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, list_items);
setListAdapter(adapter);
}*/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_XML_title, container, false);
createListView(view);
// Inflate the layout for this fragment
return view;
}
private void createListView(View view)
{
lView1 = (ListView) view.findViewById(R.id.ListViewID);
//Set option as Multiple Choice. So that user can able to select more the one option from list
lView1.setAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, list_items));
}
}
Some people suggest extending ListFragment for a fragment that uses a List View. My experience has been that is more trouble than it's worth.
Set up the Activity's java file as follows:
public class ActivityName extends FragmentActivity {
public static Context appContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_project);
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
setTitle("WoodenSideProject");
ActionBar.Tab tab1 = actionBar.newTab().setText("Tab1");
ActionBar.Tab tab2 = actionBar.newTab().setText("Tab2");
ActionBar.Tab tab3 = actionBar.newTab().setText("Tab3");
Fragment Fragment1Name = new Fragment1Name();
Fragment Fragment2Name = new Fragment2Name();
Fragment Fragment3Name = new Fragment3Name();
tab1.setTabListener(new MyTabsListener(Fragment1Name));
tab2.setTabListener(new MyTabsListener(Fragment2Name));
tab3.setTabListener(new MyTabsListener(Fragment3Name));
actionBar.addTab(tab1);
actionBar.addTab(tab2);
actionBar.addTab(tab3);
}
Within the same Activity create the following class:
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
//do what you want when tab is reselected, I do nothing
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_placeholder, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
}
I don't know if others have had as much trouble as I implementing action bar tabs with fragments, but if they are I hope this helps. Any suggestions for better implementations would be greatly appreciated.
I've done stuff like this before and this is a super simple example but I can't seem to get it working using actionbarsherlock v4.1.
This is the main activity
public class VanityActivity extends SherlockFragmentActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
//restore
}
com.actionbarsherlock.app.ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setHomeButtonEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
com.actionbarsherlock.app.ActionBar.Tab tab1 = actionBar.newTab();
tab1.setText("Website");
tab1.setTabListener(new HeaderTabListener(getApplicationContext()));
tab1.setTag(1);
actionBar.addTab(tab1);
com.actionbarsherlock.app.ActionBar.Tab tab2 = actionBar.newTab();
tab2.setText("Portfolio");
tab2.setTabListener(new HeaderTabListener(getApplicationContext()));
tab2.setTag(2);
actionBar.addTab(tab2);
com.actionbarsherlock.app.ActionBar.Tab tab3 = actionBar.newTab();
tab3.setText("Team");
tab3.setTabListener(new HeaderTabListener(getApplicationContext()));
tab3.setTag(3);
actionBar.addTab(tab3);
}
}
And my HeaderTabListener class:
public class HeaderTabListener implements
com.actionbarsherlock.app.ActionBar.TabListener {
private Context context;
public HeaderTabListener(Context context){
this.context = context;
}
#Override
public void onTabSelected(com.actionbarsherlock.app.ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
int i=((Integer)tab.getTag()).intValue();
if(tab.getPosition()==0){
ft.replace(android.R.id.content, CompanyFragment.newInstance(i));
}else if(tab.getPosition()==1){
ft.replace(android.R.id.content, PortfolioFragment.newInstance(i));
}
}
#Override
public void onTabUnselected(com.actionbarsherlock.app.ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
Log.v("Tab selected", tab.getText().toString());
}
#Override
public void onTabReselected(com.actionbarsherlock.app.ActionBar.Tab tab, android.support.v4.app.FragmentTransaction ft) {
Log.v("Tab selected2", tab.getText().toString());
}
}
And finally one of the fragments (both fragments are the same but the text in each layout is different)
public class PortfolioFragment extends SherlockFragment {
private static final String KEY_POSITION="position";
private static final String KEY_TEXT="text";
static PortfolioFragment newInstance(int position) {
PortfolioFragment frag=new PortfolioFragment();
Bundle args=new Bundle();
args.putInt(KEY_POSITION, position);
frag.setArguments(args);
return(frag);
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View result=inflater.inflate(R.layout.fragment_portfolio, container, false);
int position=getArguments().getInt(KEY_POSITION, -1);
return(result);
}
}
So when it first loads the the tabs are all displayed correctly, the first one his highlighted and the text in CompanyFragment layout displays. But then I am unable to click any of the other tabs to change the content and my logs inside of onTabSelected just never gets called. Any thoughts? Thanks for reading.
First off, let me tell you that I have no experience with ActionBarSherlock. I looked at your code to get a few ideas for my application. Seeing as it hasn't been answered since you posted it a few month ago, I would like to share my first impression.
As far as I know, ActionBarSherlock exposes the same functionality as the most recent Android APIs. Therefore, I do think that you are missing a simple method call. You would need to call commit() (Android Developer Guide reference) after you replace the fragment. Therefore, change the line, and all similar lines from;
ft.replace(android.R.id.content, PortfolioFragment.newInstance(i));
to
ft.replace(android.R.id.content, PortfolioFragment.newInstance(i)).commit();.
I hope this will solve your problem although I do realise you state that the ònTabSelected()` method is never called. Without debugging the difference between the problems would, however, seem transparent.