Не удается поймать событие нажатия кнопки "Домой" на панели инструментов
Я реализовал новейшую библиотеку appcompat и с помощью Toolbar
как панель действий. Но проблема в том, что я не могу поймать событие нажатия кнопки "Домой" / кнопки гамбургера Я попробовал и посмотрел все, но, похоже, не нашел аналогичной проблемы.
Это мое Activity
учебный класс:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Set up the drawer.
navDrawerFragment =
(NavigationDrawerFragment) getSupportFragmentManager()
.findFragmentById(R.id.navigation_drawer);
navDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout),
toolbar);
}
И это мой класс NavigationDrawerFragment:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
currentSelectedPosition = savedInstanceState.getInt(
STATE_SELECTED_POSITION);
fromSavedInstanceState = true;
}
// Select either the default item (0) or the last selected item.
selectItem(currentSelectedPosition);
}
@Override
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Indicate that this fragment would like
// to influence the set of actions in the action bar.
setHasOptionsMenu(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
drawerListView = (ListView) inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
drawerListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
selectItem(position);
}
});
//mDrawerListView.setAdapter();
//mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
return drawerListView;
}
public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
fragmentContainerView = getActivity().findViewById(fragmentId);
this.drawerLayout = drawerLayout;
// set a custom shadow that overlays the main
// content when the drawer opens
drawerLayout.setDrawerShadow(
R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view
// with items and click listener
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the navigation drawer and the action bar app icon.
drawerToggle = new ActionBarDrawerToggle(
getActivity(),
drawerLayout,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
// If the user hasn't 'learned' about the drawer,
// open it to introduce them to the drawer,
// per the navigation drawer design guidelines.
if (!userLearnedDrawer && !fromSavedInstanceState) {
drawerLayout.openDrawer(fragmentContainerView);
}
// Defer code dependent on restoration of previous instance state.
drawerLayout.post(new Runnable() {
@Override
public void run() {
drawerToggle.syncState();
}
});
drawerLayout.setDrawerListener(drawerToggle);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Forward the new configuration the drawer toggle component.
drawerToggle.onConfigurationChanged(newConfig);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("cek", "item selected");
if (drawerToggle.onOptionsItemSelected(item)) {
Log.d("cek", "home selected");
return true;
}
return super.onOptionsItemSelected(item);
}
когда я щелкаю пункт меню, вызывается журнал "пункт выбран". Но когда я нажимаю кнопку "Домой", открывается навигационная панель, но журнал "Дом выбран" никогда не вызывается. Я поставил onOptionsItemSelected
метод внутри моего Activity
также, но это все еще не называют.
12 ответов
Если вы хотите знать, когда щелкнул дом, AppCompatActivity
тогда вы должны попробовать это так:
Сначала скажите Android, что хотите использовать свой Toolbar
как твой ActionBar
:
setSupportActionBar(toolbar);
Затем установите Home для отображения через setDisplayShowHomeEnabled
как это:
getSupportActionBar().setDisplayShowHomeEnabled(true);
Наконец, послушайте события клика на android.R.id.home
как обычно:
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == android.R.id.home) {
Timber.d("Home pressed");
}
return super.onOptionsItemSelected(menuItem);
}
Если вы хотите знать, когда нажимается кнопка навигации на Toolbar
в классе, отличном от AppCompatActivity
Вы можете использовать эти методы, чтобы установить значок навигации и прослушивать события щелчка на нем. Значок навигации появится в левой части вашего Toolbar
где раньше была кнопка "домой".
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_nav_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("cek", "home selected");
}
});
Если вы хотите знать, когда гамбургер нажимается и когда открывается ящик, вы уже прослушиваете эти события через onDrawerOpened
а также onDrawerClosed
поэтому вы захотите узнать, соответствуют ли эти обратные вызовы вашим требованиям.
mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// event when click home button
}
});
в моем случае этот код работает идеально
Вот как я делаю это, чтобы вернуться к правому фрагменту, иначе, если у вас есть несколько фрагментов на одном уровне, он вернется к первому, если вы не переопределите поведение кнопки "Назад" на панели инструментов.
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
Я думаю, что правильное решение с поддержкой библиотеки 21 заключается в следующем
// action_bar is def resource of appcompat;
// if you have not provided your own toolbar I mean
Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
if (toolbar != null) {
// change home icon if you wish
toolbar.setLogo(this.getResValues().homeIconDrawable());
toolbar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//catch here title and home icon click
}
});
}
Я обработал кнопку Назад и Домой в Навигационном Ящике как
public class HomeActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private ActionBarDrawerToggle drawerToggle;
private DrawerLayout drawerLayout;
NavigationView navigationView;
private Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
resetActionBar();
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(this);
//showing first fragment on Start
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).replace(R.id.content_fragment, new FirstFragment()).commit();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
//listener for home
if(id==android.R.id.home)
{
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
onBackPressed();
else
drawerLayout.openDrawer(navigationView);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START);
else
super.onBackPressed();
}
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Begin the transaction
Fragment fragment = null;
// Handle navigation view item clicks here.
int id = item.getItemId();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (id == R.id.nav_companies_list) {
fragment = new FirstFragment();
// Handle the action
}
// Begin the transaction
if(fragment!=null){
if(item.isChecked()){
if(getSupportFragmentManager().getBackStackEntryCount()==0){
drawer.closeDrawers();
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}else{
removeAllFragments();
getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}
return true;
}
public void removeAllFragments(){
getSupportFragmentManager().popBackStackImmediate(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
public void replaceFragment(final Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.replace(R.id.WikiCompany, fragment).addToBackStack("")
.commit();
}
public void updateDrawerIcon() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
Log.i("", "BackStackCount: " + getSupportFragmentManager().getBackStackEntryCount());
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
drawerToggle.setDrawerIndicatorEnabled(false);
else
drawerToggle.setDrawerIndicatorEnabled(true);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 50);
}
public void resetActionBar()
{
//display home
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
}
public void setActionBarTitle(String title) {
getSupportActionBar().setTitle(title);
}
}
и в каждом onViewCreated
Я звоню
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((HomeActivity)getActivity()).updateDrawerIcon();
((HomeActivity) getActivity()).setActionBarTitle("List");
}
Я немного изменил DrawerLayout, чтобы получать события и иметь возможность использовать и событие, например, если вы хотите использовать actionToggle как назад, если вы находитесь в подробном представлении:
public class ListenableDrawerLayout extends DrawerLayout {
private OnToggleButtonClickedListener mOnToggleButtonClickedListener;
private boolean mManualCall;
public ListenableDrawerLayout(Context context) {
super(context);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListenableDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Sets the listener for the toggle button
*
* @param mOnToggleButtonClickedListener
*/
public void setOnToggleButtonClickedListener(OnToggleButtonClickedListener mOnToggleButtonClickedListener) {
this.mOnToggleButtonClickedListener = mOnToggleButtonClickedListener;
}
/**
* Opens the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal openDrawer method
*
* @param drawerView
*/
public void openDrawerManual(View drawerView) {
mManualCall = true;
openDrawer(drawerView);
}
/**
* Closes the navigation drawer manually from code<br>
* <b>NOTE: </b>Use this function instead of the normal closeDrawer method
*
* @param drawerView
*/
public void closeDrawerManual(View drawerView) {
mManualCall = true;
closeDrawer(drawerView);
}
@Override
public void openDrawer(View drawerView) {
// Check for listener and for not manual open
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleOpenDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.openDrawer(drawerView);
}
@Override
public void closeDrawer(View drawerView) {
// Check for listener and for not manual close
if (!mManualCall && mOnToggleButtonClickedListener != null) {
// Notify the listener and behave on its reaction
if (mOnToggleButtonClickedListener.toggleCloseDrawer()) {
return;
}
}
// Manual call done
mManualCall = false;
// Let the drawer layout to its stuff
super.closeDrawer(drawerView);
}
/**
* Interface for toggle button callbacks
*/
public static interface OnToggleButtonClickedListener {
/**
* The ActionBarDrawerToggle has been pressed in order to open the drawer
*
* @return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleOpenDrawer();
/**
* The ActionBarDrawerToggle has been pressed in order to close the drawer
*
* @return true if we want to consume the event, false if we want the normal behaviour
*/
public boolean toggleCloseDrawer();
}
}
Попробуйте этот код
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == android.R.id.home){
//You can get
}
return super.onOptionsItemSelected(item);
}
Добавьте приведенный ниже код в ваш метод onCreate()
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
В моем случае я должен был поставить значок с помощью:
toolbar.setNavigationIcon(R.drawable.ic_my_home);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
А затем прослушайте события щелчка со стандартным onOptionsItemSelected и android.R.id.home id
Для тех, кто ищет реализацию Xamarin (поскольку события в C# выполняются по-другому), я просто создал это NavClickHandler
Класс следующим образом:
public class NavClickHandler : Java.Lang.Object, View.IOnClickListener
{
private Activity mActivity;
public NavClickHandler(Activity activity)
{
this.mActivity = activity;
}
public void OnClick(View v)
{
DrawerLayout drawer = (DrawerLayout)mActivity.FindViewById(Resource.Id.drawer_layout);
if (drawer.IsDrawerOpen(GravityCompat.Start))
{
drawer.CloseDrawer(GravityCompat.Start);
}
else
{
drawer.OpenDrawer(GravityCompat.Start);
}
}
}
Затем назначили пользовательскую кнопку меню гамбургера следующим образом:
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
SupportActionBar.SetDefaultDisplayHomeAsUpEnabled(false);
this.drawerToggle.DrawerIndicatorEnabled = false;
this.drawerToggle.SetHomeAsUpIndicator(Resource.Drawable.MenuButton);
И наконец, назначил переключателю меню выдвижного ящика ToolbarNavigationClickListener типа класса, который я создал ранее:
this.drawerToggle.ToolbarNavigationClickListener = new NavClickHandler(this);
И тогда у вас есть пользовательская кнопка меню с обработкой событий клика.
Помимо ответа, предоставленного , есть еще одна возможная причина, по которой событие щелчка могло не быть MrEngineer13записано в
onOptionsSelected
метод. Возможно, вы наложили компонент интерфейса на XML-файл макета. Таким образом, всякий раз, когда вы пытаетесь нажать кнопку «Домой», вы нажимаете только кнопку
DrawerLayout
, но не кнопку "Домой", расположенную под ним.
Все, что вам нужно сделать сейчас, это переставить
Toolbar
в соответствующем XML-файле макета, чтобы он не блокировался другими компонентами пользовательского интерфейса.
Программно я попытался вызвать
bringToFront()
метод на
toolbar
(
toolbar.bringToFront()
). Однако в контексте моего приложения это не кажется решением.
Самый простой подход, который мы могли бы сделать, - это изменить иконку дома на известную иконку и сравнить рисунки (потому что иконка android.R.id.home может отличаться для разных версий API).
поэтому установите панель инструментов как панель действий SetSupportActionBar(_toolbar);
_toolbar.NavigationIcon = your_known_drawable_here;
for (int i = 0; i < _toolbar.ChildCount; i++)
{
View v = _toolbar.GetChildAt(i);
if (v is ImageButton)
{
ImageButton imageButton = v as ImageButton;
if (imageButton.Drawable.GetConstantState().Equals(_bookMarkIcon.GetConstantState()))
{
//here v is the widget that contains the home icon you can add your click events here
}
}
}
Так я реализовал предварительный дизайн материала, и, кажется, он все еще работает, теперь я перешел на новый Toolbar
, В моем случае я хочу войти в систему, если пользователь попытается открыть боковую навигацию во время выхода из системы (и поймать событие, чтобы боковая навигация не открывалась). В вашем случае вы не могли return true;
,
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!isLoggedIn() && item.getItemId() == android.R.id.home) {
login();
return true;
}
return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}