Reputation: 630
I have an AppCompatActivity and some Fragments. The back button on the action bar not works on in AboutFragment
.
The Activity has no menu inflated, while the Fragment only has a back button in the action bar.
Fragment menu is visible, but the back button doesn't react at all when tapped.
The AboutFragment
is getting showed on clicking the info icon from the actionbar.
While clicking on the i
icon, the bellow method works inside MainActivity
.
@Override
public void onInfoSelected() {
abf = (AboutFragment) getSupportFragmentManager().findFragmentByTag(ABOUT_FRAGMENT_TAG);
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right,
android.R.anim.slide_in_left, android.R.anim.slide_out_right);
// ft.hide(pf);
//ft.hide(cf);
ft.hide(tlf);
ft.show(abf);
ft.addToBackStack(null);
ft.commit();
}
then the back button inside AboutFragment doesn't call onOptionsItemSelected()
method inside the Fragment.
When debugging, I can see that both onCreateOptionsMenu()
for Fragment and Activity get called, but when tapping buttons no onOptionsItemSelected()
gets called, neither from Activity nor from Fragment.
its been two days I am searching and googling, nothing worked for me. any help would be appriciated.
Activity Java code
package me.declangao.jiasazsales.app;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import me.declangao.jiasazsales.R;
import me.declangao.jiasazsales.model.Post;
public class MainActivity extends AppCompatActivity implements
RecyclerViewFragment.PostListListener, PostFragment.PostListener,
TabLayoutFragment.TabLayoutListener, SearchResultFragment.SearchResultListener,
CommentFragment.CommentListener,AboutFragment.AboutListener {
private static final String TAG = MainActivity.class.getSimpleName();
public static final String TAB_LAYOUT_FRAGMENT_TAG = "TabLayoutFragment";
public static final String POST_FRAGMENT_TAG = "PostFragment";
public static final String COMMENT_FRAGMENT_TAG = "CommentFragment";
public static final String ABOUT_FRAGMENT_TAG = "AboutFragment";
private FragmentManager fm = null;
private TabLayoutFragment tlf;
private PostFragment pf;
private CommentFragment cf;
private SearchResultFragment srf;
private AboutFragment abf;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
fm = getSupportFragmentManager();
// Setup fragments
tlf = new TabLayoutFragment();
pf = new PostFragment();
cf = new CommentFragment();
srf = new SearchResultFragment();
abf=new AboutFragment();
FragmentTransaction ft = fm.beginTransaction();
ft.add(android.R.id.content, abf, ABOUT_FRAGMENT_TAG);
ft.add(android.R.id.content, pf, POST_FRAGMENT_TAG);
ft.add(android.R.id.content, cf, COMMENT_FRAGMENT_TAG);
ft.add(android.R.id.content, tlf, TAB_LAYOUT_FRAGMENT_TAG);
ft.hide(pf);
ft.hide(cf);
ft.hide(abf);
ft.show(tlf);
ft.commit();
}
/**
* Invoked when a post in the list is selected
*
* @param post Selected Post object
*/
@Override
public void onPostSelected(Post post, boolean isSearch) {
// Find the fragment in order to set it up later
pf = (PostFragment) getSupportFragmentManager().findFragmentByTag(POST_FRAGMENT_TAG);
// Set necessary arguments
Bundle args = new Bundle();
args.putInt("id", post.getId());
args.putString("title", post.getTitle());
args.putString("date", post.getDate());
args.putString("author", post.getAuthor());
args.putString("content", post.getContent());
args.putString("url", post.getUrl());
//args.putString("thumbnailUrl", post.getThumbnailUrl());
args.putString("featuredImage", post.getFeaturedImageUrl());
// Configure PostFragment to display the right post
pf.setUIArguments(args);
// Show the fragment
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right,
android.R.anim.slide_in_left, android.R.anim.slide_out_right);
if (!isSearch) { // Hide TabLayoutFragment if this is not search result
ft.hide(tlf);
} else { // Otherwise, hide the search result, ie. SearchResultFragment.
ft.hide(srf);
}
ft.show(pf);
ft.addToBackStack(null);
ft.commit();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
//do something here like
Log.e("menu Test","rom Main activity");
int backStackEntryCount
=getSupportFragmentManager().getBackStackEntryCount();
if (backStackEntryCount > 0) {
getSupportFragmentManager().popBackStack();
}
return true;
}
return false;
}
/**
* Invoked when a search query is submitted
*
* @param query Selected Post object
*/
@Override
public void onSearchSubmitted(String query) {
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right,
android.R.anim.slide_in_left, android.R.anim.slide_out_right);
// Send query to fragment using factory method
srf = SearchResultFragment.newInstance(query);
ft.add(android.R.id.content, srf);
ft.hide(tlf);
ft.addToBackStack(null);
ft.commit();
}
@Override
public void onInfoSelected() {
abf = (AboutFragment) getSupportFragmentManager().findFragmentByTag(ABOUT_FRAGMENT_TAG);
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right,
android.R.anim.slide_in_left, android.R.anim.slide_out_right);
// ft.hide(pf);
//ft.hide(cf);
ft.hide(tlf);
ft.show(abf);
ft.addToBackStack(null);
ft.commit();
}
/**
* Invoked when comment menu is selected
*
* @param id ID of the article, assigned by WordPress
*/
@Override
public void onCommentSelected(int id) {
cf = (CommentFragment) getSupportFragmentManager().findFragmentByTag(COMMENT_FRAGMENT_TAG);
Bundle args = new Bundle();
args.putInt("id", id);
// Setup CommentFragment to display the right comments page
cf.setUIArguments(args);
FragmentTransaction ft = fm.beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right,
android.R.anim.slide_in_left, android.R.anim.slide_out_right);
ft.hide(pf);
//ft.hide(abf);
ft.show(cf);
ft.addToBackStack(null);
ft.commit();
}
/**
* Intercept back button event, reset ActionBar if necessary
*/
@Override
public void onBackPressed() {
resetActionBarIfApplicable();
super.onBackPressed();
}
/**
* Simulate a back button press when home is selected
*/
@Override
public void onHomePressed() {
resetActionBarIfApplicable();
fm.popBackStack();
}
/**
* Reset TabLayoutFragment's ActionBar if necessary
*/
private void resetActionBarIfApplicable() {
Log.d(TAG, "SearchResultFragment is visible: " + srf.isHidden());
if (srf.isVisible()) {
tlf.resetActionBar();
}
}
// Commented out coz we will let fragments handle their own Options Menus
/*
@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);
//Log.e("Erroraaa","aaaaa");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.e("menu","activity: action home has clicked");
switch (item.getItemId()){
case android.R.id.home:
onBackPressed();
return false;
}
return super.onOptionsItemSelected(item);
}
*/
}
AboutFragment
package me.declangao.jiasazsales.app;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import me.declangao.jiasazsales.R;
/**
* Fragment to display a Info about Jiasaz company.
* Activities that contain this fragment must implement the
* {@link AboutFragment.AboutListener} interface
* to handle interaction events.
*/
public class AboutFragment extends Fragment {
private AboutListener mListener;
private Toolbar toolbar;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRetainInstance(true);
this.setHasOptionsMenu(true);
}
// @Override
// public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Log.e("Menu:created","Menu");
//
//// super.onCreateOptionsMenu(menu, inflater);
//// menu.clear();
// inflater.inflate(R.menu.menu_post, menu);
// super.onCreateOptionsMenu(menu, inflater);
// }
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.e("Menu:selected","Menu");
if (item.getItemId() == android.R.id.home) {
mListener.onHomePressed();
}
return false;
}
public AboutFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.about_layout, container, false);
toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);
((MainActivity) getActivity()).setSupportActionBar(toolbar);
((MainActivity) getActivity()).getSupportActionBar().setHomeButtonEnabled(true);
((MainActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
((MainActivity) getActivity()).getSupportActionBar().setTitle( "www.Jiasaz.com");
Log.e("Menu: fragment created","onCreaate()");
return rootView;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (AboutListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement AboutListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface AboutListener {
void onHomePressed();
//void onInfoSelected();
}
}
and this is my AboutFragment xml code
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
android:layoutDirection="rtl"
android:textDirection="rtl"
tools:context="me.declangao.jiasazsales.app.AboutFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutDirection="rtl"
android:textDirection="rtl"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:layoutDirection="rtl"
android:textDirection="rtl"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutDirection="rtl"
android:textDirection="rtl"
android:padding="15dp"
android:orientation="vertical">
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:text="ئهم ئاپه لهلایهن كۆمپانیای جیاساز دروست كراوه"
android:textAppearance="@style/TextAppearance.AppCompat.Light.SearchResult.Title" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="214dp"
android:src="@drawable/jiasazlogo" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:text="كۆمپانیای جیاساز بۆ خزمهتگوزاری و چارهسهری تهكنهلۆجی، دروستكردنی وێبسایت و ئاپی مۆبایل و سیستهمی دام و دهزگاكان و ماركێتهكان"
android:textAppearance="@style/TextAppearance.AppCompat.Light.SearchResult.Title" />
<TextView
android:id="@+id/textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="all"
android:clickable="true"
android:text="@string/link"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
Upvotes: 4
Views: 3609
Reputation: 22832
You can set an instance of OnMenuItemClickListener
directly on the Toolbar
. Remember that you should not use Activity.setSupportActionBar(Toolbar)
.
public class AboutFragment extends Fragment {
// ...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.about_layout, container, false);
toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);
toolbar.inflateMenu(R.menu.menu_about_fragment);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.some_menu) {
// do sth...
return true; // event is handled.
}
return false;
}
});
// ...
}
// ...
}
.
To enable back button for a stand alone Toolbar
, set its default icon in xml
file using app:navigationIcon="?attr/homeAsUpIndicator"
:
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:layoutDirection="rtl"
android:textDirection="rtl"
app:navigationIcon="?attr/homeAsUpIndicator" />
Then set a listener for it
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// back button is pressed
mListener.onHomePressed();
}
});
Upvotes: 3
Reputation: 2889
You can use onPrepareOptionsMenu(Menu menu)
in you fragment class for listening to you action bar menus...
@Override
public void onPrepareOptionsMenu(Menu menu)
{
super.onPrepareOptionsMenu(menu);
// to get an item of menu from action bar you can do it like...
// this below line will find an item of menu with id action_search...
MenuItem searchMenuItem = menu.findItem(R.id.action_search);
// like this you can find other menu items
// another example is
MenuItem infoMenuItem = menu.findItem(R.id.action_info);
}
I'm using search view in my fragment class practically for searching...
Upvotes: 0
Reputation: 9990
You described everything properly, those are limitations of the platform. To workaround it you need to use onOptionsItemSelected() in MainActivity, insert there code that you already use in another method:
abf = (AboutFragment) getSupportFragmentManager().findFragmentByTag(ABOUT_FRAGMENT_TAG);
then as you have the fragment you can invoke some method from the fragment and possibly get return value to know if the back is handled or not and if something more needs to be done...
Upvotes: 0
Reputation: 324
First reason is that you have'nt properly implemented onCreateOptionsMenu()
and onOptionsItemSelected()
@Override methods in Activity
so uncomment that Activity
can also call their respective super
methods.
Second reason is that your onCreateOptionsMenu()
code is commented which needs not
to be. Important thing is that super super.onCreateOptionsMenu(menu, inflater);
must be called to draw the menu of the Fragment
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
And also change change onOptionsItemSelected()
in Fragment
to this:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.e("Menu:selected","Menu");
if (item.getItemId() == android.R.id.home) {
mListener.onHomePressed();
return true;
}else{
return super.onOptionsItemSelected(item);
}
}
And now in Activity
change your onCreateOptionsMenu()
to this:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
and onOptionsItemSelected()
to this:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
Upvotes: -1