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);
Related
Disclaimer: This is the first app I am building so I am learning the hard way to use fragments first, so my code is all over the place.
I have menu items inside a navigation view that loads fine however the menu item clicks don't work. It doesn't crash it just stares at me. I would like to use an intent to display a fragment and I am lost from changing and trying so many different options.
XML FOR NAV DRAWER & MENU ITEMS:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_pageone"
android:background="#drawable/rygg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarThumbVertical="#color/primary_dark_color"
tools:openDrawer="start"
tools:context="com.android.nohiccupsbeta.pageone">
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.design.widget.NavigationView
android:id="#+id/navigation_header_container"
app:headerLayout="#layout/header"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:itemIconTint="#color/category_vodka"
app:itemTextColor="#color/primary_dark_color"
app:menu="#menu/drawermenu"
android:layout_gravity="start" >
</android.support.design.widget.NavigationView>
</FrameLayout>
</android.support.v4.widget.DrawerLayout>
JAVA:
public class pageone extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
DrawerLayout mDrawerLayout;
ActionBarDrawerToggle mToggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pageone);
setupDrawer();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.drawermenu, menu);
return true;
}
/**
*
* #param item For the hamburger button
* #return
*/
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mToggle.onOptionsItemSelected(item)){
return true;
}
switch (item.getItemId()) {
case R.id.itemWhiskey:
Intent whiskeyIntent = new Intent(pageone.this, whiskeyActivity.class);
startActivity(whiskeyIntent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Make sure the drawer open and closes in sync with UI visual
* #param savedInstanceState
*/
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mToggle.syncState();
}
/**
* Function to make sure all the drawer open & closes properly
*/
public void setupDrawer() {
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDrawerLayout = (DrawerLayout) findViewById(R.id.activity_pageone);
mToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open, R.string.drawer_closed) {
#Override
public void onDrawerClosed(View closeView) {
Toast.makeText(pageone.this, "Happy You Learned", Toast.LENGTH_SHORT).show();
super.onDrawerClosed(closeView);
invalidateOptionsMenu();
}
#Override
public void onDrawerOpened(View openView) {
Toast.makeText(pageone.this, "Effects Of Alcohol", Toast.LENGTH_SHORT).show();
super.onDrawerOpened(openView);
invalidateOptionsMenu();
}
};
mDrawerLayout.addDrawerListener(mToggle);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
MenuItem itemWhiskey = (MenuItem) findViewById(R.id.itemWhiskey);
itemWhiskey.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem itemWhiskey) {
FragmentManager fm = getSupportFragmentManager();
Fragment effectsFragment = fm.findFragmentById(R.id.frame_container2);
if (effectsFragment == null) {
effectsFragment = new WhiskeyFragment();
fm.beginTransaction().add(R.id.frame_container2, effectsFragment).commit();
getSupportActionBar().setTitle("Whiskey");
itemWhiskey.setChecked(true);
mDrawerLayout.closeDrawers();
}
return true;
}
});
mDrawerLayout.closeDrawer(GravityCompat.START);
return true;
}
}
XML FOR FRAGMENT:
<FrameLayout 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"
android:id="#+id/frame_container2"
tools:context="com.android.nohiccupsbeta.WhiskeyFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/frag_whiskey_skin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="8dp"
android:textColor="#000000"
android:textSize="16sp" />
<ImageButton
android:id="#+id/expand_collapse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:background="#android:color/transparent"
android:src="#drawable/ic_expand_more"
android:padding="16dp"/>
</FrameLayout>
JAVA:
public class WhiskeyFragment extends Fragment {
private TextView mWhiskeySkin;
#Override
public void onViewCreated(View view, #Nullable Bundle SavedInstanceState) {
super.onViewCreated(view, SavedInstanceState);
getActivity().setTitle("WHISKEY EFFECTS");
mWhiskeySkin = (TextView) view.findViewById(R.id.frag_whiskey_skin);
mWhiskeySkin.setText(R.string.whiskey_skin);
hasOptionsMenu();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_whiskey, container, false);
hasOptionsMenu();
return v;
}
}
XML FOR SECOND ACTIVITY:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
JAVA:
public class whiskeyActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_whiskey);
}
public class Whiskeyed {
private String whiskeySkin;
private String whiskeyBrain;
public String getWhiskeySkin(){
return whiskeySkin;
}
public String getWhikeyBrain(){
return whiskeyBrain;
}
public void setWhiskeySkin(String whiskey_skin){
this.whiskeySkin = whiskey_skin;
}
public void setWhiskeyBrain(String whiskeyBrain) {
this.whiskeyBrain = whiskeyBrain;
}
}
}
try to change to content of your onNavigationItemSelected of your pageone.java
from here:
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
MenuItem itemWhiskey = (MenuItem) findViewById(R.id.itemWhiskey);
itemWhiskey.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem itemWhiskey) {
FragmentManager fm = getSupportFragmentManager();
Fragment effectsFragment = fm.findFragmentById(R.id.frame_container2);
if (effectsFragment == null) {
effectsFragment = new WhiskeyFragment();
fm.beginTransaction().add(R.id.frame_container2, effectsFragment).commit();
getSupportActionBar().setTitle("Whiskey");
itemWhiskey.setChecked(true);
mDrawerLayout.closeDrawers();
}
return true;
}
});
mDrawerLayout.closeDrawer(GravityCompat.START);
return true;
}
to here:
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.activity_pageone); // ID of your drawerLayout
int id = item.getItemId();
switch (id) {
case R.id.menu1: // Change this as your menuitem in menu.xml.
// Your fragment code goes here..
FragmentManager fm = getSupportFragmentManager();
Fragment effectsFragment = fm.findFragmentById(R.id.frame_container2);
if (effectsFragment == null) {
effectsFragment = new WhiskeyFragment();
fm.beginTransaction().add(R.id.frame_container2, effectsFragment).commit();
getSupportActionBar().setTitle("Whiskey");
itemWhiskey.setChecked(true);
mDrawerLayout.closeDrawers();
}
break;
case R.id.menu2: // Change this as your menuitem in menu.xml.
// or Your fragment code goes here...
break;
}
mDrawerLayout.closeDrawer(GravityCompat.START, true);
return true;
}
I am using appcompat v7 and support design 23.1.1.
I want to add back button in the hamburger button animation, when back pressed application will go back to started page.
Now in my application I have hamburger button. When it is pressed in main window (marked with orange rectangle) material navigation opens, selected Home (marked as red rectangle) when the application navigates to selected window there are hamburger (yellow rectangle) button again, and I would like to change it.
My MainActivity.java:
public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {
private static String TAG = MainActivity.class.getSimpleName();
private Toolbar mToolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private FragmentDrawer drawerFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.view_pager);
viewPager.setAdapter(new PagerAdapter(this));
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(viewPager);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getSupportFragmentManager().popBackStack();
}
});
drawerFragment = (FragmentDrawer)
getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
return true;
case R.id.action_search:
Toast.makeText(getApplicationContext(), "Search action is selected!", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new HomeFragment();
title = getString(R.string.title_home);
break;
case 1:
fragment = new FriendsFragment();
title = getString(R.string.title_friends);
break;
case 2:
fragment = new MessagesFragment();
title = getString(R.string.title_messages);
break;
default:
break;
}
if (fragment != null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack(fragment.getClass().getSimpleName())
.commit();
mToolbar.setTitle(title);
}
}
}
FragmentDrawer.java:
public class FragmentDrawer extends Fragment {
private static String TAG = FragmentDrawer.class.getSimpleName();
private RecyclerView recyclerView;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private NavigationDrawerAdapter adapter;
private View containerView;
private static String[] titles = null;
private FragmentDrawerListener drawerListener;
public FragmentDrawer() {
}
public void setDrawerListener(FragmentDrawerListener listener) {
this.drawerListener = listener;
}
public static List<NavDrawerItem> getData() {
List<NavDrawerItem> data = new ArrayList<>();
// preparing navigation drawer items
for (int i = 0; i < titles.length; i++) {
NavDrawerItem navItem = new NavDrawerItem();
navItem.setTitle(titles[i]);
data.add(navItem);
}
return data;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// drawer labels
titles = getActivity().getResources().getStringArray(R.array.nav_drawer_labels);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflating view layout
View layout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
recyclerView = (RecyclerView) layout.findViewById(R.id.drawerList);
adapter = new NavigationDrawerAdapter(getActivity(), getData());
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
#Override
public void onClick(View view, int position) {
drawerListener.onDrawerItemSelected(view, position);
mDrawerLayout.closeDrawer(containerView);
}
#Override
public void onLongClick(View view, int position) {
}
}));
return layout;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, final Toolbar toolbar) {
containerView = getActivity().findViewById(fragmentId);
mDrawerLayout = drawerLayout;
mDrawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getActivity().invalidateOptionsMenu();
}
#Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
toolbar.setAlpha(1 - slideOffset / 2);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.post(new Runnable() {
#Override
public void run() {
mDrawerToggle.syncState();
}
});
}
public static interface ClickListener {
public void onClick(View view, int position);
public void onLongClick(View view, int position);
}
static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
public interface FragmentDrawerListener {
public void onDrawerItemSelected(View view, int position);
}
}
NavDrawerItem.java:
public class NavDrawerItem {
private boolean showNotify;
private String title;
public NavDrawerItem() {
}
public NavDrawerItem(boolean showNotify, String title) {
this.showNotify = showNotify;
this.title = title;
}
public boolean isShowNotify() {
return showNotify;
}
public void setShowNotify(boolean showNotify) {
this.showNotify = showNotify;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
DrawerActivity.java :
public class DrawerActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener{
private Toolbar mToolbar;
private FragmentDrawer drawerFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
drawerFragment = (FragmentDrawer)
getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
// display the first navigation drawer view on app launch
displayView(0);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
return true;
case R.id.action_search:
Toast.makeText(getApplicationContext(), "Search action is selected!", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new HomeFragment();
title = getString(R.string.title_home);
break;
case 1:
fragment = new FriendsFragment();
title = getString(R.string.title_friends);
break;
case 2:
fragment = new MessagesFragment();
title = getString(R.string.title_messages);
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, fragment);
fragmentTransaction.commit();
// set the toolbar title
getSupportActionBar().setTitle(title);
}
}
}
Try this way in your xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="start"
android:background="#android:color/transparent"
android:minHeight="?attr/actionBarSize"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/toolBarStyle"
app:titleTextAppearance="#style/Toolbar.TitleText" />
<android.support.v4.widget.DrawerLayout 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:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
android:fitsSystemWindows="true">
<RelativeLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="0dp"
android:background="#android:color/transparent" />
<fragment
android:id="#+id/navigation_drawer"
class="com.buzzintown.consumer.drawer.NavigationDrawerFragment"
android:layout_width="310dp"
android:layout_height="match_parent"
android:layout_gravity="start"
tools:layout="#layout/drawer_layout" />
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
If the activity figured in your third picture is a new one, you can just add the follow code in the new activity`s onCreate() method. it may help...
final ActionBar toolbar = getSupportActionBar();
if (toolbar != null) {
toolbar.setDisplayHomeAsUpEnabled(true);
}
If it`s in one same activity, and just different fragments through viewpager, use the Toolbar.setNavigationIcon() to change your up icon.
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 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();
}
}