Android Studio: How to implement backbutton in ActionBar from Fragments - java

I'm having trouble implementing a backbutton in the ActionBar in a Fragment. Since this is a Fragment I don't have access to getSupportActionBar(); and each time I use this, or similar code:
ActionBar actionBar = getActivity().getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
only results in NullPointerExceptions.
I've looked at numerous similar questions on StackOverflow but most of them are specified to Activities or AppCompatActivities, which do not work in Fragments. Using
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
only results in NullPointerExceptions. The other similar questions and answers have not helped me with this problem so I had to create a new topic.
This is where I get the error:
public class ExampleFragment extends Fragment{
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
ActionBar actionBar = getActivity().getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true); //This results in NullPointerException
inflater.inflate(R.menu.example_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
getActivity().getSupportFragmentManager().popBackStack();
return true;
}
return super.onOptionsItemSelected(item);
}
}

You need to receive supportActionBar.
public class ExampleFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
setHasOptionsMenu(true);
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
ActionBar actionBar = ((AppCompatActivity)requireActivity()).getSupportActionBar();
if (actionBar!=null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
requireActivity().getSupportFragmentManager().popBackStack();
return true;
}
return super.onOptionsItemSelected(item);
}
}

I did not get this to work so I changed the structure of the View and made it to an Activity which has more support in dealing with this issue.
#Override
protected void onCreate(#Nullable Bundle savedInstance){
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}

Related

onCreateOptionsMenu() does not work in Fragment

I am trying to implement a search Filter in my Fragment, but it does not let me. I used the same code in Activity before and it worked. Whenever I type something, the onCreateOptionsMenu() does not get called. The App looks like this : [![app Picture][1]][1]
As you can see I type something in the top and it won't get filtered.
My Fragment code: `
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
setMenuVisibility(false);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View RootView = inflater.inflate(R.layout.fragment_tab1, container, false);
if(getArguments() != null){
String yourText = getArguments().getString("interessen");
System.out.println(yourText);
}`
.
.
.
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menuevents, menu);
super.onCreateOptionsMenu(menu, inflater);
MenuItem searchitem = menu.findItem(R.id.searchEvent);
//searchitem.setVisible(false);
final SearchView searchView = (SearchView) searchitem.getActionView();
final List<Event> allEvents = new ArrayList<>();
allEvents.addAll(eventList);
searchitem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
eventList.clear();
eventList.addAll(allEvents);
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
eventList.clear();
eventList.addAll(allEvents);
return true;
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
eventListAdapter.getFilter().filter(newText);
return false;
}
});
I did not copy the EventListAdapter in, becuase this should work just fine. Its just that the Fragment does not get Access to the SearchItem.
Anybody? :)
[1]: https://i.stack.imgur.com/JkLcL.png
You've called setMenuVisibility(), which means your Fragment is specifically opting out of having its menu being shown. It is expected that when your menu isn't shown, onCreateOptionsMenu() is not triggered.
Remove that line of code to have your menu actually be visible.

Spinner items lost on navigate change in Android Studio

I have created an Android Studio project and i have MainActivity, FirstFragment and SecondFragment. On the FirstFragment I have an spinner element. When the app starts the spinner is filled with values, when I switch from the First to the second Fragment and back, the values are gone.
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
PublicCameras Cameras = new PublicCameras();
//get the spinner from the xml.
Spinner dropdown = findViewById(R.id.cameraList); // This element loses his values when navigating to SecondFragment and back
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, Cameras.GetNamesEn());
dropdown.setAdapter(adapter);
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);
}
}
FirstFragment
public class FirstFragment extends Fragment {
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false);
}
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
}
}
SecondFragment
public class SecondFragment extends Fragment {
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_second, container, false);
}
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.button_second).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NavHostFragment.findNavController(SecondFragment.this)
.navigate(R.id.action_SecondFragment_to_FirstFragment);
}
});
}
}
I would like to point out that on rotating the values are being set again because of re-entering the function onCreateOptionsMenu. What is the best practice to keep values on a layout change?
Thank you for your time !
You're getting this issue cause when you move from one fragment to other android destorys the fragment and recreates that fragment when returned back this happens in the screen orientation case too. In order to handle this override OnSavedInstance method in you're code
There is a little hack you can make it work.
first override
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putStringArray("YOUR_KEY", "YOUR_OBJECT");//chnage this with you're object name
}
Now in you're onViewCreated use the SavedInstance variable and get that stringArray using the key and pass this to the spinner.
Try this and if you faced any issue do comment.

SearchView in fragment (inflated menu in activity)

I get NPE on SearchView.OnQueryTextListener.
/res/menu/order_toolbar.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/order_menu_search"
android:icon="#drawable/ic_search"
android:title="#string/order_menu_search"
app:actionViewClass="android.support.widget.v7.SearchView"
app:showAsAction="ifRoom|withText" />
<item
android:id="#+id/order_menu_checkmark"
android:icon="#drawable/ic_checkmark"
android:title="#string/order_toolbar"
app:showAsAction="ifRoom|withText" />
ActivityOrder.java
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.order_toolbar, menu);
mMenuCheckmark = menu.findItem(R.id.order_menu_checkmark);
mMenuCheckmark.setVisible(false);
return super.onCreateOptionsMenu(menu);
}
FragmentOrder.java
#Override
public void onPrepareOptionsMenu(Menu menu){
MenuItem menuItem = menu.findItem(R.id.order_menu_search);
SearchView searchView = (SearchView) menuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
Toast.makeText(getActivity(), "" +newText, Toast.LENGTH_SHORT).show();
return false;
}
});
}
I'm inflating menu in Activity (i need to hide checkmark and enable it later after the user made some input, all the logic is in the activity), and in Fragment, I have RecyclerView and I need to implement search (in the toolbar). So basically, I need to access that SearchView INSIDE FRAGMENT only.
I have been trying to find anything but nothing helps, if I inflate menu in fragment then I get doubled icons in the toolbar.
setHasOptionsMenu(true);
is already added in onCreate
Also i tried this:
1. inflate the menu in fragment (removed onCreateOptionsMenu in activity)
2. passed menuItem (checkmark) back to activity trough interface so i can access checkmark
3. still getting NPE if i set listener on searchview
I make option menu in fragment. Like this,
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
...
setHasOptionsMenu(true);
...
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_menu, menu);
menu.findItem(R.id.menu_1).setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_bar_search));
searchView = (SearchView) menu.findItem(R.id.menu_1).getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
return false;
}
});
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
#Override
public boolean onClose() {
return false;
}
});
....
}
Not sure, you call "searchView.setOnQueryTextListener" from onCreateOptionsMenu.
Solved:
mMenuSearch = (SearchView) menu.findItem(R.id.order_menu_search).getActionView();
mMenuSearch.setOnQueryTextListener(this);
added implements SearchView.OnQueryTextListener on Fragment and 2 new Override methods onQueryTextSubmit and onQueryTextChanged

Access int data of View Class from Activity

I have a Drawscreen.class file which the main activity and Drawthegraph.class which extends view. I have a method in Drawthegraph.class which I need to call from Drawscreen.class.How can I do that?
Drawscreen.class-
public class Drawscreen extends ActionBarActivity
{
//LinearLayout linear=(LinearLayout)findViewById(R.id.main_layout);
//draw=(Drawthegraph)findViewById(R.id.main_layout);
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
ActionBar actionbar=getSupportActionBar();
actionbar.show();
View drawthegraph=new Drawthegraph(this);
setContentView(drawthegraph);
drawthegraph.setBackgroundColor(color.Ivory);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.drawscreen, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
case R.id.undo:/*Call method of view here*/
break;
}
return super.onOptionsItemSelected(item);
}
}
Drawthegraph.class
public class Drawthegraph extends View
{
private int lines;
----
----
public void decrease_lines() /*Call this function from Drawscreen*/
{
if(lines>0)
{
lines--;
}
}
Use your drawthegraph variable as an instance field:
public class Drawscreen extends ActionBarActivity
{
//LinearLayout linear=(LinearLayout)findViewById(R.id.main_layout);
//draw=(Drawthegraph)findViewById(R.id.main_layout);
private Drawthegraph drawthegraph;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
ActionBar actionbar=getSupportActionBar();
actionbar.show();
this.drawthegraph=new Drawthegraph(this);
setContentView(drawthegraph);
drawthegraph.setBackgroundColor(color.Ivory);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.drawscreen, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
case R.id.undo:/*Call method of view here*/
drawthegraph.decrease_lines();
break;
}
return super.onOptionsItemSelected(item);
}
}
Your Drawthegraph object must be a field of your Activity:
public class Drawscreen extends ActionBarActivity {
Drawthegraph drawthegraph;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
...
drawthegraph = new Drawthegraph(this);
setContentView(drawthegraph);
drawthegraph.setBackgroundColor(color.Ivory);
}
...
then you can call wherever you want in your Drawscreen:
drawthegraph.decrease_lines();

Where to write java code in Android app

I just started learning how to create Android app and I'm stuck with methods in MainActivity.java. I don't know where to write my java code because the app is crashing.
package com.cidecode.loveometer;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
Things you want to be created when the activity is started should be in the onCreate method (buttons and onClickListeners etc). If for example you have a button you have stated an onClick name for in the xml file (rather than put an onClickListener on it) then you can put that function where you like as long as it is not after the last curly brace that finishes the activity. You should try the new boston tutorials on youtube, I found they explained a lot and helped me understand where I actually needed to put things.

Categories