I have 3 fragments in a TabLayout as seen here http://imgur.com/a/Z9dTQ
Whenever I start the application, it opens the explorer tab, and I can switch to the search tab and the searchview works perfectly. If I switch to explorer and back to search, it still works.
My SearchView does not use a searchable activity, but instead searches with an onQueryTextChange listener. Below the SearchView is a LinearLayout with 30 TextViews whose text are changed by searching.
However, if I switch to the quiz tab and back to search, the SearchView text remains, but the TextViews are reset to their default values of "gone", like so: http://imgur.com/a/L4RvE. Trying to search now using the SearchView does not work.
It seems that switching to the quiz tab deflates my search layout, and when I switch back, it inflates the search layout but does not instantiate the SearchView properly. When I try to search again, OnQueryTextChange is not called. I cannot figure out why it does this.
The problem started when I added a SearchView to QuizLayout.xml, and added code for a second SearchView to the onCreateOptionsMenu in MainActivity for the quiz tab. However even after commenting it out and making sure all IDs were correct, the problem still happens.
Below is my code, with some (hopefully) irrelevant code omitted.
My SearchFragment:
package com.example.ryans45attcdie.chess;
public class SearchFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.search_fragment, container, false);
return v;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
searchLayout =
(LinearLayout)getView().findViewById(R.id.searchLayoutS);
}
}
My QuizFragment: (empty for debugging)
public class QuizFragment extends Fragment {}
My MainActivity:
public class MainActivity extends AppCompatActivity {
TextView sname1;//(etc.)
ArrayList<TextView> masterNameListS;
List<Fragment> fragments = new Vector<>();
ArrayList<String> listItems = new ArrayList<String>();
ArrayAdapter<String> adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//set up fragments in tabs
fragments.add(Fragment.instantiate(this, QuizFragment.class.getName()));
fragments.add(Fragment.instantiate(this,
ExplorerFragment.class.getName()));
fragments.add(Fragment.instantiate(this,
SearchFragment.class.getName()));
PagerAdaptor adaptor = new PagerAdaptor(getSupportFragmentManager(),
fragments);
ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setAdapter(adaptor);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(pager);
tabLayout.getTabAt(0).setText("QUIZ");
tabLayout.getTabAt(1).setText("EXPLORE");
tabLayout.getTabAt(2).setText("SEARCH");
adapter = new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.list_content, listItems);
pager.setCurrentItem(1);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
sname1 = (TextView) findViewById(R.id.sname1); //(etc.)
final ArrayList<TextView> masterNameListS = new ArrayList<>();
masterNameListS.add(sname1); //(etc.)
// Get the SearchView and set the searchable configuration
SearchManager searchManagerS = (SearchManager)
getSystemService(Context.SEARCH_SERVICE);
SearchView searchViewS = (SearchView) findViewById(R.id.searchViewS);
// Assumes current activity is the searchable activity
ComponentName cnS = new ComponentName(this, SearchableActivity.class);
searchViewS.setSearchableInfo(searchManagerS.getSearchableInfo(cnS));
searchViewS.setIconifiedByDefault(false); // Do not iconify the widget;
expand it by default
searchViewS.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s) {
return true;
}
#Override
public boolean onQueryTextChange(String s) {
//parse search string and set TextView texts here
return true;
}
});
return true;
}
#Override
public booleafn onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
And PagerAdapter:
package com.example.ryans45attcdie.chess;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.WindowManager;
import java.util.List;
public class PagerAdaptor extends FragmentPagerAdapter {
private List<Fragment> fragments;
public PagerAdaptor(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int i) {
return fragments.get(i);
}
#Override
public int getCount() {
return fragments.size();
}
}
My QuizLayout.xml is empty.
My SearchLayout.xml creates all the TextViews with no text and Visibility.GONE.
Thanks very much for the help guys,
Stephen
Solved it :)
The issue was that ViewPager keeps, by default, only one off-screen tab in memory. Because my explorer tab was opened first, this was stored in memory. When I switched from search to quiz, my ViewPager decided to delete the search tab, and keep the explorer tab.
To fix this, put your_View_Pager_here.setOffscreenPageLimit(number_to_store); in your MainActivity onCreate method.
Related
My fragment is not refreshing when I swipe back, so I want to know how I can refresh it when I swipe it back. I have seen many different answers online, but I don't why they don't work in my situation. It would be highly appreciated if someone could help me out, thanks.
public class MainActivity extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
}
#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) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Profile tab1 = new Profile();
return tab1;
case 1:
Puzzles tab2 = new Puzzles();
return tab2;
default:
return null;
}
}
#Override
public int getCount() {
// Show 3 total pages.
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Profile";
case 1:
return "Puzzles";
}
return null;
}
}
}
I have tried setOffscreenPageLimit(0), detach attach fragment in onTabSelected, using FragmentStatePagerAdapter, notifyDataSetChanged(), and even
public int getItemPosition(Object object) {
return POSITION_NONE;
}
this doesn't work too. So I hope someone could help.
If you want to refresh the data in a particular Fragment, you have to do 2 things,
Store the updated data into Activity
Show the updated data in onResume() in that particular Fragment
If you want your data to be saved even after killing the app, store it in SharedPreference. Hope it helps!
On your fragment class add this.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
//Try adapter.notifyDataSetChanged or something like passing the new(updated) data to adapter from here.
}
}
Hope it helps.
I have many fragments they're shown in 2 tab layouts using FragmentStatePagerAdapter in each fragment there is a Recycler view and I want to use a search bar in the app bar to filter results.
First I did this using the onQueryTextChange listener in the onCreateOptionsMenu and it worked fine with a couple fragments but when I added the implementation to the other fragments (just ctrl+c and ctrl+v) it stopped working, no results even on fragments that used to work i then read here that it was better to stick the onQueryTextChange listener in onPrepareOptionsMenu in an attempt to avoid an issue with invalidateOptionsMenu but i decided to give that a try which also worked and then when i added the methods to all my other fragments yet again it fails but it does work on a handful of fragments, oddly these happen to be all attached to the same parent fragment but the code for the 4 parent fragments, and for calling them is identical.
A different way around this I've read is creating an interface and using that from my main activity by getting a reference to the current fragment but then id have to get the currently showing fragment from my viewpager which i dont know is possible can anyone weigh in on this for me,
Many thanks
And thanks for the great edit lol
EDIT
Tried the interface approach to no avail although I'm still a beginner i do need to find the attached fragment and with a fragmentstateviewpager its just not possible without using hacks there must be some reason why it works in some and not in others and sometimes not at all
Edit 2
So im still fiddling with this and ive had almost no replies so lets flesh this out a little so i was adding the menu layout in the main activity like 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.dashboard, menu);
SearchView searchView =
(SearchView)menu.findItem(R.id.action_search).getActionView();
SearchManager searchManager = (SearchManager)
getSystemService(SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
return true;
}
and then adding a listener on to it from the fragment in onPrepareOptionsMenu like this
#Override
public void onPrepareOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//in this instance we wont as it will create a duplicate
SearchView searchView = (SearchView)
menu.findItem(R.id.action_search).getActionView();
searchView.setOnQueryTextListener(null);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
showResults(newText);
return false;
}
});
super.onPrepareOptionsMenu(menu);
}
and i have called setHasOptionsMenu(true) in onCreateView of the fragment, this works perfectly but i have about 20 fragments to cycle through and when I add this to the other fragments it fails it either does nothing or makes the view blank or in rare occasions works, but that for me says my code is okay and maybe its a lifecycle thing, ive tried calling it from the onCreateOptionsMenu of the fragments and achieved the same results, and ive tried not calling anything from the MainActivity in onCreateOptions except inflating the menu and allow the fragments to call the search activity using
SearchView searchView = (SearchView)menu.findItem
(R.id.action_search).getActionView();
SearchManager searchManager = (SearchManager)
getActivity().getSystemService(getActivity().SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager.getSearchableInfo
(getActivity().getComponentName()));
which again works up to around 8 fragments but my 20 or so just causes it to fall on its sword, is there something im not doing that could help
Edit 3
Okay so by adding some, checking it, adding some more, checking it, it seems to be a problem with my parent fragments so I have main activity 4 fragments that each hold a fragment state pager that each holds 7 or so fragments if I add the methods for the query listener to the first 7 or so fragments in the first parent fragment they all work beautifully, if I then add the methods to the next set of 7 or so fragments in the second parent only the second parents child fragments work, if I then quit my app and open it again only the first parents fragments work, will continue investigating any help appreciated I'll post the code for my parent fragments here soon.
EDIT 4
Just going to add the code i use for the parent fragments and the fragmentstatepager from my main activity
so from my Main activity i set the fragmentstatepager like this
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new
ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new sentenceMakers(), "QUICKS");
adapter.addFrag(new tabFragOne(), "NOUNS");
adapter.addFrag(new tabFragTwo(), "VERBS");
adapter.addFrag(new tabFragThree(), "OBJECTS");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentStatePagerAdapter {
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 void restoreState(Parcelable arg0, ClassLoader arg1) {
//do nothing here! no call to super.restoreState(arg0, arg1);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
and my parent fragments look like this
public class sentenceMakers extends Fragment{
public ImageView imageView;
private ViewPager viewPager;
public static TabLayout tabLayout;
public sentenceMakers() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate
(R.layout.tab_frag_one, container, false);
// Inflate the layout for this fragment
//setRetainInstance(true);
viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
}
private void setupTabIcons() {
TextView tabZero2 = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabZero2.setText("FAVOURITES");
//tabOne.setGravity(View.TEXT_ALIGNMENT_CENTER);
tabZero2.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_star_white_24dp, 0, 0);
tabLayout.getTabAt(0).setCustomView(tabZero2);
TextView tabZero = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabZero.setText("FREQUENTS");
//tabOne.setGravity(View.TEXT_ALIGNMENT_CENTER);
tabZero.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_people_outline_white_24dp, 0, 0);
tabLayout.getTabAt(1).setCustomView(tabZero);
TextView tabOne = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabOne.setText("PRONOUNS");
//tabOne.setGravity(View.TEXT_ALIGNMENT_CENTER);
tabOne.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_accessibility_white_24dp, 0, 0);
tabLayout.getTabAt(2).setCustomView(tabOne);
TextView tabTwo = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabTwo.setText("CONJUCTIONS");
tabTwo.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_add_white_24dp, 0, 0);
tabLayout.getTabAt(3).setCustomView(tabTwo);
TextView tabThree = (TextView)
LayoutInflater.from(getActivity()).inflate(R.layout.custom_tab, null);
tabThree.setText("ADJECTIVES");
tabThree.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.ic_favorite_border_white_24dp, 0, 0);
tabLayout.getTabAt(4).setCustomView(tabThree);
tabLayout.getTabAt(0).getCustomView().setSelected(true);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new
ViewPagerAdapter(getChildFragmentManager());
adapter.addFrag(new favouriteCards(), "FAVOURITES");
adapter.addFrag(new predictedCards(), "FREQUENTS");
adapter.addFrag(new pronouns(), "PRONOUNS");
adapter.addFrag(new conjuctions(), "CONJUNCTIONS");
adapter.addFrag(new Others(), "ADJECTIVES");
viewPager.setAdapter(adapter);
}
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 addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
}
}
still struggling with this and i cannot for the life of me work out why it would work in one lot of fragments untill i add it to the next set, its the same thing with the same code it must just be initializing the last fragments that are asking for it can anyone help me here?
Thanks for any help
Basically, there is a thing that you have to keep in mind when you use fragments: do not keep references to your fragments: just create them and add to your layout, or provide to your ViewPager but then use other methods to retrieve them, like FragmentManager.findFragmentBy...
That said, your code shoud be (let me simplify with just two fragments):
Main activity
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new MyViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
}
class MyViewPagerAdapter extends FragmentStatePagerAdapter {
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new sentenceMakers();
case 1:
return new tabFragOne();
// add here fragments for any other position
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch(position) {
case 0:
return "QUICKS";
case 1:
return "NOUNS";
// add here titles for any other position
}
}
}
sentenceMakers
The code you will have to use in your sentenceMakers Fragment is very similar to the previous one, but you will have to use the child fragmentManager (as you did in your code) and again, do not keep your fragments in a List, let the system create them when needed.
ok i fixed it so the problem is that the parent fragmentstatepager loads fragmentA + fragmentB into memory, then the child fragmentstatepagers load there own childfragmentA + childfragmentB so we now have 2 parents and 4 children, onPrepareOptionsMenu is called from the child fragments so the the first is loaded childfragmentA(child of fragmentA) and then childFragmentA(child of fragmentB) is loaded and steals the search view, my 'fix' for this is probably a little crude i'm self taught and i'm not very aware of how to manage memory or if its bad to keep hold of references etc, i digress, in the parent fragment i check which fragment is visible using
setMenuVisibility(final boolean visible)
and in there i set a public static boolean and check for it in my childfragments and it works flawlessly for me as mentioned this is probably a terrible thing to do hopefully someone here can give a better solution
check which parent is visible
public static boolean tabFragOneVisible;
#Override
public void setUserVisibleHint(boolean isVisible){
super.setUserVisibleHint(isVisible);
if(!isVisible){
tabFragOneVisible = false;
}else{
tabFragOneVisible = true;
}
}
check if parent is visible hook up search view
#Override
public void onPrepareOptionsMenu(Menu menu) {
// need to check if fragment is visible
if (tabFragOne.tabFragOneVisible) {
SearchView searchView = (SearchView)
menu.findItem(R.id.action_search).getActionView();
SearchManager searchManager = (SearchManager) getActivity()
.getSystemService(getActivity().SEARCH_SERVICE);
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getActivity().getComponentName()));
// searchView.setOnQueryTextListener(null);
searchView.setOnQueryTextListener(new
SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
showResults(newText);
return false;
}
});
}
else{
}
super.onPrepareOptionsMenu(menu);
}
Maybe, it'll still help someone struggling to make one SearchView work for multiple Fragments. I found that onQueryTextListener would work on Fragment 1 (where the SearchView is initially created) but would not fire on Fragment 2,3, etc.
Fragments 2 worked when onPrepareOptionsMenu is overridden and onViewCreated includes a setHasOptionsMenu(true). For example:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
...the rest of your code goes here...
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) item.getActionView();
searchView.setOnQueryTextListener(this);
super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
Toast.makeText(getActivity(),"It Worked!!",Toast.LENGTH_SHORT).show();
return true;
}
I have tab layout in android with viewpager in my Main Activity. I have three Tab with three Fragment. And in first fragment i have button i want to intent on second tab from that button on click. how to intent please help me.
Here is my Code
public class MainActivity extends AppCompatActivity {
//Declaring All The Variables Needed
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private ViewPagerAdapter viewPagerAdapter;
public static final String PREFS_NAME = "MyPrefsFile";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences settings = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
String name = settings.getString("first", "str1");
//str1 = intent.getStringExtra("first");
Toast.makeText(MainActivity.this, "" + name, Toast.LENGTH_SHORT).show();
toolbar = (Toolbar) findViewById(R.id.toolbar);
tabLayout = (TabLayout) findViewById(R.id.tabs);
viewPager = (ViewPager) findViewById(R.id.viewpager);
FragmentManager manager = getSupportFragmentManager();
ViewPagerAdapter adapter = new ViewPagerAdapter(manager);
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setTabsFromPagerAdapter(adapter);
tabLayout.setTabTextColors(ContextCompat.getColorStateList(this, R.drawable.tab_selector));
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
setSupportActionBar(toolbar);
final FloatingActionMenu floatingActionsMenu=(FloatingActionMenu) findViewById(R.id.material_design_android_floating_action_menu);
final FloatingActionButton floatingActionButton1=(FloatingActionButton)findViewById(R.id.material_design_floating_action_menu_item1);
floatingActionButton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Table", Toast.LENGTH_SHORT).show();
viewPager.setCurrentItem(0);
floatingActionsMenu.close(true);
}
});
FloatingActionButton floatingActionButton2=(FloatingActionButton)findViewById(R.id.material_design_floating_action_menu_item2);
floatingActionButton2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Order", Toast.LENGTH_SHORT).show();
viewPager.setCurrentItem(1);
floatingActionsMenu.close(true);
}
});
FloatingActionButton floatingActionButton3=(FloatingActionButton)findViewById(R.id.material_design_floating_action_menu_item3);
floatingActionButton3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Logout", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
Intent tologin=new Intent(MainActivity.this,LoginPage.class);
startActivity(tologin);
return true;
}
return super.onOptionsItemSelected(item);
}
}
All the fragments are within the same ViewPager and you just want to go one to another fragment you can do like this...
The view pager is in Activity but the Button is inside Fragment so you need to do this create this method inside your activity
public void navigateFragment(int position){
viewPager.setCurrentItem(position, true);
}
and call inside your OnClickListener method of fragment:
((MainActivity)getActivity()).navigateFragment(POSITION_YOU_WANNA_SELECT);
Hope this will help you.
Recommended approach : you can implement a listener in second fragment and create reference in first fragment.
after onclick of a button from 1st fragment call method of listener which is defined in second fragment.
Second approach : you can maintain a static data from 1st fragment and on click just load 2nd fragment and access that static data.
I'm working to implement a SearchView on my Fragment's RecyclerView as shown here. When the user taps the search button I want the Menu Item for the SearchView to Override the toolbar and display the area for them to search. If I don't use my custom style for the toolbar it works fine but when I do it get the images below.
Here is what I am currently getting:
This is the class that the EventListActivity inherits from:
public abstract class SingleFragmentActivity extends AppCompatActivity {
protected abstract Fragment createFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.eventcalendar_activity_fragment);
// Manages our fragments. We can call it to add a fragment to an activity in code
FragmentManager fm = getSupportFragmentManager();
// Check if fragment of R.id already exits
// The FragmentManager saves out the list of fragments on rotation destruction or memory reclaim
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
// If the the fragment does not exist, create it
if(fragment == null) {
fragment = createFragment();
// Create a new fragment transaction, include one add operation in it, and then commit it
fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
}
}
}
This creates the fragment that manages and works with the RecyclerView:
public class EventListActivity extends SingleFragmentActivity {
#Override
protected Fragment createFragment() {
// Setting arguments for the new fragment created from the intent from EventFeedResultWrapper
EventListFragment fragment = new EventListFragment();
fragment.setArguments(getIntent().getExtras());
return fragment;
}
}
Fragment that holds the RecyclerViewthat the SearchView will interface with. This is where the search menu button is inflated. It is where I've been trying to modify the toolbar:
public class EventListFragment extends Fragment {
private RecyclerView mEventRecyclerView;
private EventAdapter mAdapter;
// Telling the FragmentManager that it is
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
((AppCompatActivity)getActivity()).getSupportActionBar().setCustomView(R.layout.action_bar_center);
View sabView = ((AppCompatActivity)getActivity()).getSupportActionBar().getCustomView();
TextView titleTxtView = (TextView) sabView.findViewById(R.id.action_bar_title);
titleTxtView.setText("Events Calendar");
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowCustomEnabled(true);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.eventcalendar_fragment_event_list, container, false);
mEventRecyclerView = (RecyclerView) view.findViewById(R.id.event_recycler_view);
// RecyclerView requires a layout manager to work, layout manager is in charge of position items on screen
mEventRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
updateUI();
return view;
}
// Populate the menu instance
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.eventcalendar_menu, menu);
}
// When we edit a EventActivity this saves it back to the EventListActivity
// onResume over onStart because we cannot assume the activity will be stopped
// when another activity is in front of it. If the other activity is transparent
// then the activity might just get paused. If it is paused then onStart() will not be called
// but on resume will be called.
// NOTE: In general onResume() is the safest place to take action to update a fragment's view
#Override
public void onResume() {
super.onResume();
updateUI();
}
private void updateUI() {
// Read in the events saved in to EventFeedResultWrapper by the Async task in ParseEventFeedTask
EventFeedResultWrapper wrapper = (EventFeedResultWrapper) getArguments().getSerializable(ParseEventFeedTask.EXTRA_RESULTS_LIST);
// Make sure wrapper is not null, it will NEVER be null
if(wrapper == null){
throw new RuntimeException("Error: The wrapper is null!");
}
// Get all the events from the wrapper/serializable
List<Event> events = wrapper.getEventFeedResults();
// Gets the context that we don't use rofl
EventCal eventCal = EventCal.get(getActivity());
// Add all the events we got from the wrapper to our event manager eventCal
eventCal.addEvents(events);
// Check to see if the EventAdapter is already setup
if(mAdapter == null) {
mAdapter = new EventAdapter(events);
mEventRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.notifyDataSetChanged();
}
}
//Adapter here - removed code since it doesn't do anything with the toolbar
//RecycleView onClickLister - removed code since it doesn't do anything with the toolbar
}
This is the custom XML Style
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/action_bar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#ffffff"
android:textSize="24dp"/>
</LinearLayout>
Event Menu XML
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/action_search"
android:title="Search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
</menu>
Did you missed android:orientation="vertical". The text is displaying vertically. You want horizontal right?
Oh nvm i didn't understood it at first. The problem must be the inflating of the custom view, for some reason it seems it keeps the original view there and inflated it somewhere else. Give me 1s i'll update the answer when i find the issue
Check here: getSupportActionBar().setCustomView(view) does not fill entire actionbar
Similar problem. First and Second answer
EDIT2: Remove the code from EventListFragment onCreate. You don't need to inflate a searchView, you can use the default one.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main, menu);
super.onCreateOptionsMenu(menu, inflater);
setOptionsMenu(menu);
}
public void setOptionsMenu(Menu menu) {
MenuItem search = menu.findItem(R.id.search);
SearchView searchView;
/**
* Setup the SearchView
*/
SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
final boolean[] modifiedOriginal = {false};
searchView = (SearchView) search.getActionView();
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(((Activity) context).getComponentName()));
MenuItemCompat.setOnActionExpandListener(search, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
...
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
...
return true;
}
});
final EditText et = ButterKnife.findById(searchView, android.support.v7.appcompat.R.id.search_src_text);
et.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
String s = editable.toString();
if (!s.equals("") && !s.equals(" ")) {
...
}
}
});
ButterKnife.findById(searchView, android.support.v7.appcompat.R.id.search_close_btn).setOnClickListener(
view -> {
...
et.setText("");
}
);
}
}
You can leave your menu xml as it is.
I am working with the support library ActionBar because I'm using an older minimum SDK. In the activity, I am using FragmentTabHost because I have 3 tabs. The ActionBar also has a SearchView, so when a search is made, the 3rd tab is switched out with the results of the search.
I am able to get intput from the SearchView, but I am unable to switch out the 3rd tab when I have a search result. I am using this as an example:
Dynamically changing the fragments inside a fragment tab host?
My problem is that when I try to get a reference to the 3rd tab, and I use getSupportFragmentManager().findFragmentByTag() , the fragment being returned is always null.
My base container that helps in swapping multiple fragments in a tab:
public class BaseContainerFragment extends Fragment{
public void replaceFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container_framelayout, fragment);
transaction.commit();
getChildFragmentManager().executePendingTransactions();
}
public boolean popFragment() {
//Log.e("test", "pop fragment: " + getChildFragmentManager().getBackStackEntryCount());
boolean isPop = false;
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
return isPop;
}
}
A container that extends BaseContainerFragment
public class LibraryContainerFragment extends BaseContainerFragment {
private boolean mIsViewInited;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.e("test", "tab 1 oncreateview");
return inflater.inflate(R.layout.container_fragment, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.e("test", "tab 1 container on activity created");
if (!mIsViewInited) {
mIsViewInited = true;
initView();
// setRetainInstance(true);
}
}
private void initView() {
Log.e("test", "tab 1 init view");
replaceFragment(new LibraryFragment, false);
}
}
The xml used to switch out fragments (container_fragment.xml):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container_framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
My main activity:
public class BookSetup extends ActionBarActivity {
// For accessing SlidingMenu library
private SlidingMenu slidingMainMenu;
private FragmentTabHost mTabHost;
private SlidingMenu slidingContextMenuFavourites;
private SlidingMenu slidingContextMenuMyPrayerBook;
private SlidingMenu slidingContextMenuLibrary;
private android.support.v4.app.FragmentManager fragmentManager;
LibraryContainerFragment libraryContainerFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Settings for the clickable top-left button in the action bar
android.support.v7.app.ActionBar bar = getSupportActionBar();
bar.setDisplayHomeAsUpEnabled(false);
bar.setHomeButtonEnabled(true);
bar.setIcon(R.drawable.main_menu);
// Setting up tabbed navigation
bar.setDisplayShowTitleEnabled(false);
// Setting up tabs
fragmentManager = getSupportFragmentManager();
mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
mTabHost.setup(this, fragmentManager, R.id.realtabcontent);
// Add tabs
mTabHost.addTab(mTabHost.newTabSpec("Favourites").setIndicator(getString(R.string.favourites) ),
FavouritesFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("My Book").setIndicator(getString(R.string.my_book) ),
MyBookFragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("Library").setIndicator(getString(R.string.library) ),
LibraryContainerFragment.class, null);
mTabHost.setCurrentTab(2);
//mTabHost.
// Creates a sliding animation when activity is started
overridePendingTransition(R.anim.slide_in_from_right, R.anim.slide_out_to_left);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_menu_with_search_context_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
//SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
final MenuItem searchMenuItem = menu.findItem(R.id.action_search);
searchView = (android.support.v7.widget.SearchView) MenuItemCompat.getActionView(searchMenuItem);
//searchView = (SearchView)menu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
//searchView.requestFocus();
searchView.requestFocusFromTouch();
//searchView.setIconifiedByDefault(true);
// Listener for the search input found in the action bar, when the magnifying glass is
// clicked
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
// Activated when a search string is submitted
#Override
public boolean onQueryTextSubmit(String query) {
// TODO : query is the text from the search view after you clicked search
if(query != null){
// If results are found, then switch the fragments
if(!sectionsFound.isEmpty()){
// Initialize the search fragment and send bundles of data to it
SearchLibraryResultFragment fragment = new SearchLibraryResultFragment();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("values",
(ArrayList<? extends Parcelable>) sectionsFound);
bundle.putStringArrayList("names", sectionNames);
fragment.setArguments(bundle);
mTabHost.setCurrentTab(2);
libraryContainerFragment = (LibraryContainerFragment)fragmentManager.findFragmentByTag("Library");
((BaseContainerFragment) libraryContainerFragment.getParentFragment() ).replaceFragment(fragment,true );
return true;
}
});
}
}
This is the line that always returns null in BookSetup.java:
((BaseContainerFragment) libraryContainerFragment.getParentFragment() ).replaceFragment(fragment,true );
You are using the ChildFragmentManager to replace your Fragments right?
That might be your problem, instead of
libraryContainerFragment = (LibraryContainerFragment)fragmentManager.findFragmentByTag("Library");
use
libraryContainerFragment = (LibraryContainerFragment) getChildFragmentManager().findFragmentByTag("Library");