I have a tabbed view activity with 3 tabs and one fragment in each tab. Those fragments are managed by a FragmentPageAdapter linked to a viewpager.
Everything works fine until I try to have a 4th fragment (ServiceSpecifNotListFragment) that would be a nested fragment of one of the fragments (ServicesListFragment) managed by the FragmentPageAdapter.
When I try to replace the ServicesListFragment by the ServiceSpecifNotListFragment. I manage to replace only the list element from ServicesListFragment by the ServiceSpecifNotListFragment, the other view controller (a button) from ServicesListFragment remains....
I have been wondering if the problem lies in the fact that the method I use to replace the fragment by its subfragment is transaction.replace(R.id.service_list_fragment, newFragment).commit(); and service_list_fragment is the id of the listfragment main linear layout which contains the listview defined with the id: #id/android:list
The closest Q&A I found to this was this one but as far as I understood I am using the fragment container id correctly.
Here is the code and layout:
Layout of ServicesListFragment (the parent of the nested fragment)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/service_list_fragment">
<Button
android:id="#+id/addServiceButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="AddService" />
<ListView android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
<TextView android:id="#id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No data"/>
</LinearLayout>
Layout of ServiceSpecifNotListFragment(the fragment to be nested)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/service_notif_list_fragment" >
<ListView android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
<TextView android:id="#id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No data"/>
</LinearLayout>
Main activity xml layout (it is basically a reference to the pager):
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
Source code of ServiceListFragment, the call for the nesting of fragments is in the onListItemClick :
public class ServicesListFragment extends ListFragment {
private final String TAG = "ServicesListFragment";
Button addButton = null;
ServiceNotifRowAdapter adapter;
ArrayList<NotifService> list = new ArrayList<NotifService>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Activity parent = getActivity();
// some ommited code for populating adapter with list of stored subscriptions
adapter = new ServiceNotifRowAdapter(getActivity().getApplicationContext(),list);
setListAdapter(adapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.servicelist_fragment, container, false);
addButton = (Button) rootView.findViewById(R.id.addServiceButton);
MainActivity m = (MainActivity) getActivity();
addButton.setOnClickListener(m);
return rootView;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
NotifService item = (NotifService) getListAdapter().getItem(position);
Log.d(TAG, "selected service " + item.getServiceURI());
Fragment newFragment = new ServiceSpecifNotListFragment();
Bundle bundle = new Bundle();
bundle.putString("service", item.getServiceURI());
newFragment.setArguments(bundle);
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.service_list_fragment, newFragment).commit();
}
Main activity java code
public class MainActivity extends FragmentActivity implements TabListener, AddServiceDialogFragmentListener
, OnClickListener{
private final String TAG = "MQTT main activity";
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, StatusListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ServicesListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ConfigFragment.class.getName()));
mAdapter = new TabsPagerAdapter(getSupportFragmentManager(),fragments);
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : MqttApplication.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) {
}
});
// lock the screen in portrait mode
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
Tabs page adapter
public class TabsPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
private FragmentManager fm;
private final String TAG = "TabsPagerAdapter";
public TabsPagerAdapter(FragmentManager fm,List<Fragment> fragments) {
super(fm);
this.fm = fm;
this.fragments = fragments;
}
#Override
public Fragment getItem(int index) {
return this.fragments.get(index);
}
#Override
public int getCount() {
return this.fragments.size();
}
// 0 - Status, 1 Service, 2 Config (due to the order in which they have been added)
public Fragment findFragmentByPosition(int position) {
return fm.findFragmentByTag(
"android:switcher:" + R.id.pager + ":"
+ this.getItemId(position));
}
}
Just an alternate solution : implemented callbacks in your code and asked your view pager to load SpecificListNotFragment when item clicked in ServiceListFragment. Have a look and try it!
public class ServicesListFragment extends ListFragment {
private final String TAG = "ServicesListFragment";
Button addButton = null;
ServiceNotifRowAdapter adapter;
ArrayList<NotifService> list = new ArrayList<NotifService>();
private onListItemClickCallbackListener mCallback;
public interface onListItemClickCallbackListener {
public void replaceFragmentToServiveListNot();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Activity parent = getActivity();
mCallback = parent; // remember to imlement onListItemClickCallbackListener in activity else it will give error
// some ommited code for populating adapter with list of stored subscriptions
adapter = new ServiceNotifRowAdapter(getActivity().getApplicationContext(),list);
setListAdapter(adapter);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.servicelist_fragment, container, false);
addButton = (Button) rootView.findViewById(R.id.addServiceButton);
MainActivity m = (MainActivity) getActivity();
addButton.setOnClickListener(m);
return rootView;
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
NotifService item = (NotifService) getListAdapter().getItem(position);
Log.d(TAG, "selected service " + item.getServiceURI());
mCallback.replaceFragmentToServiveListNot();
}
}
public class MainActivity extends FragmentActivity implements TabListener, AddServiceDialogFragmentListener
, OnClickListener,onListItemClickCallbackListener {
private final String TAG = "MQTT main activity";
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
List<Fragment> fragments;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, StatusListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ServicesListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ConfigFragment.class.getName()));
mAdapter = new TabsPagerAdapter(getSupportFragmentManager(),fragments);
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Adding Tabs
for (String tab_name : MqttApplication.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) {
}
});
// lock the screen in portrait mode
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void replaceFragmentToServiveListNot() {
fragments.removeAll(fragments);
fragments.add(Fragment.instantiate(this, StatusListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ServiceSpecifNotListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, ConfigFragment.class.getName()));
mAdapter.notifyDataSetChanged();
}
}
Related
I am building an Android app that uses the Helpshift API. It was all working, but I am currently trying to move everything into a TabLayout, using Fragments and an ActionBar. I made a mini app to figure out functionality of the fragments without messing everything else up. I have a home screen where you click a button and it starts the activity containing the TabLayout with the Fragments. I cannot figure out how to make the embeddable support fragments show up in the TabLayout. I'm pretty new to Android, so sorry if my code is not the best. Right now the placeholder is not being replaced in the fragment transaction, and I can't figure out why. I would greatly appreciate any advice! Thank you :) Let me know if I can provide anything else
Here is my main activity class (Helpshift info has been redacted for privacy reasons, hopefully my issue can still be fixed)
public class MainActivity extends AppCompatActivity {
Context mContext;
public ConstraintLayout layout;
Activity goToFragment;
public Button start;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_screen);
mContext = getApplicationContext();
goToFragment = MainActivity.this;
start = (Button) findViewById(R.id.button);
start.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick (View view) {
launchFragments();
}
});
//HELPSHIFT SET UP
Core.init(All.getInstance());
InstallConfig installConfig = new InstallConfig.Builder()
.setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE)
.setEnableInAppNotification(true)
.build();
try {
Core.install(getApplication(),
"****APIKEY*****",
"****DOMAIN*****",
"****APPID******", installConfig);
} catch (InstallException e) {
android.util.Log.e("Helpshift", "install call : ", e);
}
}
private void launchFragments() {
Intent intent1 = new Intent(mContext, HomeTab.class);
intent1.putExtra("fragmentNumber", 0);
startActivity(intent1);
}
}
Here is my ViewPager Adapter class:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager){
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
Here is my fragment activity class:
public class HomeTab extends AppCompatActivity {
// ImageButton FindCareButton;
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
public Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getApplicationContext();
Intent intent1 = getIntent();
int var = intent1.getIntExtra("fragmentNumber", 0);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
viewPager.setCurrentItem(var);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
if (findViewById(R.id.placeholder) != null) {
if (savedInstanceState != null) {
return;
}
Fragment faqFragment = new Fragment();
faqFragment = Support.getFAQsFragment(HomeTab.this);
getSupportFragmentManager().beginTransaction().add(R.id.placeholder, faqFragment).commit();
}
}
private void setupViewPager(ViewPager viewPager){
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new FAQTab(), "FAQ");
viewPager.setAdapter(adapter);
}
}
Here is my FAQTab class:
public class FAQTab extends Fragment {
public FAQTab(){
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.faq_tab, container, false);
}
}
For layouts, my faq_tab layout is an empty FrameLayout with id "placeholder"
My home_screen layout is a ConstraintLayout with a button (id "button")
And here is my activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.sasha.fragment_tester.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/BarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabGravity="fill"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>
I have a problem with fragments and the ViewPager, my ViewPager is composed of five tabs, each one is a Fragment.
On the first load I don't have problem with these load, but when I open another fragment (Ahead the main), and go back to the main, the fragments where I was, and those, has been removed (invisible).
For fix that I need to "get away" for two pages before the central page loads.
Everything is only in API 21 (5.0.1), with Android Studio.
MainActivity.java:
public class MainActivity extends FragmentActivity {
private MainActivityFragment frag_MainActivity;
private CreditsFragment frag_Credits;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frag_MainActivity = new MainActivityFragment(this);
frag_Credits = new CreditsFragment();
switchFrag("main");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_home) {
switchFrag("main");
return true;
} else if (id == R.id.action_credits) {
switchFrag("credits");
return true;
}
return super.onOptionsItemSelected(item);
}
public void switchFrag(String view){
Fragment frag = new Fragment();
if(view.equals("main")){
getActionBar().show();
frag = new MainActivityFragment(this);
} else if(view.equals("credits")){
getActionBar().hide();
frag = new CreditsFragment();
}
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, frag)
.addToBackStack(null).commit();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
switchFrag("main");
return true;
}
return super.onKeyUp(keyCode, event);
}
public void closeApp() {
finish();
System.exit(0);
}
And the XML (activity_main.xml):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</RelativeLayout>
MainActivityFragment.java:
public class MainActivityFragment extends Fragment implements ActionBar.TabListener {
private ViewPager viewPager;
private MyAdapter mAdapter;
private ActionBar actionBar;
private String[] tabs = { "Lun", "Mar", "Merc", "Gio", "Ven"};
MainActivity main;
public MainActivityFragment(MainActivity instance) {
main = instance;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewPager = (ViewPager) main.findViewById(R.id.pager);
actionBar = main.getActionBar();
mAdapter = new MyAdapter(main.getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
if(actionBar.getTabCount() == 0){
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {}
XML (fragment_settings.xml):
<RelativeLayout 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"
tools:context=".MainActivityFragment">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
If the Adapter is needed, here it is:
public class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 5;
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
switch(position){
case 0:
return new LunFragment();
case 1:
return new MarFragment();
case 2:
return new MerFragment();
case 3:
return new GioFragment();
case 4:
return new VenFragment();
}
return null;
}
}
Replace mAdapter = new MyAdapter(main.getSupportFragmentManager()); with mAdapter = new MyAdapter(main.getChildFragmentManager());. You need to create the fragments as inner fragments of your MainActivityFragment.
So I'm new to android app writing, and I am trying to work on a practice app that I can hopefully turn into something later. I had 3 tabs in the actionbar that ran fine before I decided to try to add webview to one of them. Now it crashes with an IllegalStateException. And since I don't know too much about android at the moment, I can't seem to figure out what is wrong.
The main activity:
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
private String[] tabs = { "Web", "Facebook", "Twitter" };
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
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)
{
}
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft)
{
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
}
The WebFragment with the webview:
public class WebFragment extends Fragment
{
private String url = getString(R.string.website);
//#Override
//public void onActivityCreated(Bundle savedInstanceState)
//{
//super.onActivityCreated(savedInstanceState);
//}
#SuppressLint("SetJavaScriptEnabled")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.web_fragment, container, false);
WebView tolerableWebView = (WebView) getView().findViewById(R.id.webview);
tolerableWebView.getSettings().setJavaScriptEnabled(true);
tolerableWebView.loadUrl(url);
return rootView;
}
}
the TabsPagerAdapter:
public class TabsPagerAdapter extends FragmentPagerAdapter
{
public TabsPagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int index)
{
switch (index) {
case 0:
// Top Rated fragment activity
return new WebFragment();
case 1:
// Games fragment activity
return new FacebookFragment();
case 2:
// Movies fragment activity
return new TwitterFragment();
}
return null;
}
#Override
public int getCount()
{
// get item count - equal to number of tabs
return 3;
}
}
The webfragment xml
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
</WebView>
The main activity xml:
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Any help would be great! Thanks
Generally you get that error when you try to perform work after the Fragment is no longer attached to the Activity. In the callback that triggers the IllegalStateException add a check for isAdded: http://developer.android.com/reference/android/app/Fragment.html#isAdded()
if(!isAdded()) {
return;
}
I am using a searchview inside fragment and getting a nullpointerexception.
I don't understand why, I'm just trying to get the query...
I'm using a 3 tab fragment and the app crash when launching
MainActivity.java
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private ActionBar actionBar;
// Tab titles
private String[] tabs = { "Search", "Top", "Download", "Library" };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initilization
viewPager = (ViewPager) findViewById(R.id.pager);
actionBar = getActionBar();
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
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) {
}
});
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
}
SearchFragment.java
public class SearchFragment extends Fragment {
private SearchView searchView1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_search, container, false);
searchView1 = (SearchView) getActivity().findViewById(R.id.searchView1);
final SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
// Do something
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
// Do something
performSearch();
return true;
}
};
searchView1.setOnQueryTextListener(queryTextListener);
return rootView;
}
public void performSearch(){
Toast.makeText(getActivity(), "search performer", Toast.LENGTH_SHORT).show();
}
}
fragment_search.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#17df0d">
<SearchView
android:id="#+id/searchView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:iconifiedByDefault="false"
android:queryHint="#string/search_hint" >
</SearchView>
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/searchView1" >
</ListView>
</RelativeLayout>
Can you please tell me what i'm doing wrong and how could I succeed?
You should look for the search view in your fragment's view, not in your activity's view.
Change
searchView1 = (SearchView) getActivity().findViewById(R.id.searchView1);
to
searchView1 = (SearchView) rootView.findViewById(R.id.searchView1);
New to ActionBar and Fragments but familiar with Android in general.
I have been following a few tutorial. So far I have the following:
3 Fragments that I want to navigate between (each has an overriden onCreateView() and loads a simple view)
A custom TabListener for the ActionBar (I believe the problem is there, see bottom of post for code)
A hosting Activity in which this is all performed
The Activity code:
public class Activity_Home extends Activity
{
ActionBar actionBar;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
actionBar = getActionBar(); // Get reference to ActionBar
// Add some navigation tabs...
// 1. Enable ActionBar navigation tabs
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
// 2. Add the tabs
Tab programTab = actionBar.newTab();
Tab settingsTab = actionBar.newTab();
Tab historyTab = actionBar.newTab();
programTab.setText("Program")
.setTabListener(new TabListener<Fragment_Program>(
this, R.id.fragmentParent, Fragment_Program.class));
settingsTab.setText("Settings")
.setTabListener(new TabListener<Fragment_Settings>(
this, R.id.fragmentParent, Fragment_Settings.class));
historyTab.setText("History")
.setTabListener(new TabListener<Fragment_History>(
this, R.id.fragmentParent, Fragment_History.class));
actionBar.addTab(programTab);
actionBar.addTab(settingsTab);
actionBar.addTab(historyTab);
}
}
My Fragments:
public class Fragment_Program extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_program, null);
}
}
..
public class Fragment_History extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_history, null);
}
}
..
public class Fragment_Settings extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_settings, null);
}
}
Lastly, my TabListener which has been pretty much based on the official Google example. The fragmentContainer (int) is the XML resource ID of the LinearLayout in the Activities layout that is the direct parent of all of these Fragments.
public class TabListener <T extends Fragment> implements ActionBar.TabListener
{
private Fragment fragment;
private int fragmentContainer;
private final Activity activity;
private final Class<T> fragmentClass;
/** Constructor used each time a new tab is created.
* #param activity The host Activity, used to instantiate the fragment
* #param tag The identifier tag for the fragment
* #param fragmentClass The fragment's Class, used to instantiate the fragment
*/
public TabListener(Activity activity, int fragmentContainer, Class<T> fragmentClass)
{
this.activity = activity;
this.fragmentContainer = fragmentContainer;
this.fragmentClass = fragmentClass;
}
#Override
public void onTabReselected(Tab arg0, FragmentTransaction arg1)
{
// User selected the already selected tab. Usually do nothing.
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
// Check if the fragment is already intialized
if (fragment == null)
{
// If not, instatiate and add it to the Activity
fragment = Fragment.instantiate(activity, fragmentClass.getName());
ft.add(fragmentContainer, fragment);
}
else
{
ft.attach(fragment);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
if (fragment != null)
{
// Detach the fragment, because another one is being attached
ft.detach(fragment);
}
}
}
So the app loads, the tabs are there, I can select them but they don't seem to be linked to each other and I am not really sure how to proceed.
Any suggestions would be great!
Cheers
BONUS QUESTION: The ActionBar is also below the existing ActionBar.. goal was to replace it, not make another one underneath.. again any suggestions would be great!
Fixed it!
I changed my approach from using the Fragment Container ID (which did make and does still make more sense to me..) with String tags as per this example Good complete Fragment and ActionBar example and the official Google example.
I imagine that you want the tabs to be connected in a way that you can swipe between tabs, in order to accomplish this, you should consider a ViewPager.
Here's the XML by the way:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
Here's some sample code you can use:
public class MyTabActivity extends FragmentActivity implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
//What item on the pager is being displayed
private int mCurPagerItem = 0;
//This will be set to the pageer to handle navigation
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
final ActionBar mActionBar = getActionBar();
mActionBar.setDisplayShowHomeEnabled(false);
mActionBar.setDisplayShowTitleEnabled(false);
mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//add the tabs
mActionBar.addTab(mActionBar.newTab().setIcon(R.drawable.your_icon).setTabListener(this));
mActionBar.addTab(mActionBar.newTab().setIcon(R.drawable.your_icon2).setTabListener(this));
mActionBar.addTab(mActionBar.newTab().setIcon(R.drawable.your_icon3).setTabListener(this));
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(this);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Fragment one = new Fragment_Program();
return one ;
case 1:
Fragment two = new Fragment_Settings();
return two ;
case 2:
Fragment three = new Fragment_History();
return three ;
default:
break;
}
return null;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getString(R.string.title_one);
case 1:
return getString(R.string.title_two);
case 2:
return getString(R.string.title_three);
}
return null;
}
}
#Override
public void onPageScrollStateChanged(int arg0) {}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
#Override
public void onPageSelected(int arg0) {
//When a Page is selected, make that the current navigation item
getActionBar().setSelectedNavigationItem(arg0);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
//Back to top maybe?
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
//get the position
final int pos = tab.getPosition();
//Tell the viewpager to scroll to that page
mViewPager.setCurrentItem(pos);
mCurPagerItem = pos;
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
To answer your bonus question, on your Manifest, try adding the following line withing the specified activity tag:
android:uiOptions="splitActionBarWhenNarrow"