Не вдається зафіксувати подію домашньої кнопки на панелі інструментів


106

Я реалізував новітню бібліотеку додатків і використовував 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, але він все ще не викликається.

Відповіді:


224

Якщо ви хочете дізнатися, коли натискають будинок, AppCompatActivityто спробуйте це так:

Спочатку скажіть Android, що хочете використовувати свій Toolbarяк свій ActionBar:

setSupportActionBar(toolbar);

Потім встановіть, щоб Головна відображалася 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);
}

Якщо ви хочете дізнатися, коли на клавіші навігації натискають клавішу a, відмінну від 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ви хочете дізнатися, чи відповідають ці зворотні дзвінки вашим вимогам.


1
Спробував першу частину раніше, але це не працює. Спробував другу частину, і вона працює. Але піктограма не змінюється, якщо я зареєструю панель інструментів з навігатором. Ще одне питання: чи є заміна для setDrawerIndicatorEnabled для цього? Я намагався з цим новим ящиком навігації та отримував помилку. Дякую u
Темний Леонхарт

Друге рішення працює. Але як ми можемо виявити натиснуту кнопку будинку та кнопку висувного ящика у другому рішенні. Якщо я натискаю значок ящика, ящик не відкривається.
Dory

2
Якщо ви встановитеNavigationOnClickListener для панелі інструментів, ви втратите «рідну» поведінку ящика :(
IlyaEremin

7
Отже, зараз нам потрібен окремий слухач клацань, коли раніше у фрагментах ми могли перевірити наявність android.R.id.home в onOptionsItemSelected ()? Це насправді дуже дратує
Даніель Вілсон

1
re: Панель інструментів, якщо ви встановили новий NavigationOnClickListener (використовуючи setNavigationOnClickListener), ви можете відновити NavDrawer пізніше, якщо це доречно, зателефонувавши знову на setDrawerListener за допомогою ActionBarDrawerToggle.
страя

24
    mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
    mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // event when click home button
        }
    });

в моєму випадку цей код працює ідеально


Ви справді чудові, це спрацювало, я ніколи не думав, що мені вдасться керувати кнопкою повернення панелі інструментів через DrawerToggle ..
Сай

Щоб діяти ActionBarDrawerToggle.setToolbarNavigationClickListener, потрібно спочатку викликати це: mActionBarDrawerToggle.setHomeAsUpIndicator (R.dravable.menu_icon); mActionBarDrawerToggle.setDrawerIndicatorEnabled (помилково); а сам керувати подіями натискання. (відкрити / закрити шухляду при натисканні)
luky

10

Ось так я це роблю, щоб повернутися до правого фрагмента, інакше, якщо у вас є кілька фрагментів на одному рівні, він повернеться до першого, якщо ви не перекриєте поведінку кнопки назад на панелі інструментів.

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });

Чи є у нас в Котліні метод "Перевизначити"?
Ахіла Мадарі

@AkhilaMadari спробуйте щось подібне в Котліні: val toolbar = findViewById (R.id.toolbar) як панель інструментів setSupportActionBar (панель інструментів) toolbar.setNavigationOnClickListener {/ * зробіть щось, що ви хочете * / закінчити ()}
Маркос

3

Я думаю, що правильне рішення з підтримкою бібліотеки 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                          
        }                       
    });                 
}

в this.getResValues().homeIconDrawable(), Хто є this?
LuisComS

Це діяльність. Отримати оцінки - це мій метод, тому його тут не актуально. Setlogo приймає ідентифікатор джерела ресурсу.
Чикич Ненад

4
це допоможе користувачеві натиснути в будь-якому місці на цілій панелі інструментів, я не думаю, що про це він запитував
Міна Фаузі

1

Я обробляв кнопку "Назад" та "Головна", як у Навігаційному ящику

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");
}

0

Ось як я реалізував це передречове проектування, і, здається, він все ще працює, тепер я перейшов на нове 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);
}

Ах, я забув, я виявив, що не в змозі зафіксувати натискання кнопки додому у фрагменті, я задав тут питання і запропонував вирішити питання, яке повинно було вручну передати подію на всі ваші фрагменти. stackoverflow.com/q/21938419/1007151
darnmason

0

Я трохи змінив 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();
    }

}

0

Найпростіший підхід, який ми могли б зробити, - це змінити домашню піктограму на відому піктограму та порівняти малюнки (адже значок 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 
                    }
                }
            }

0

У моєму випадку я повинен був поставити значок, використовуючи:

toolbar.setNavigationIcon(R.drawable.ic_my_home);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);

А потім прослухайте клацання подій із замовчуванням onOptionsItemSelected та id android.R.id.home


1
Це не спрацює. android.R.id.homeніколи не вогонь
Trancer

0

Для всіх, хто шукає реалізацію 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);

А потім у вас є спеціальна кнопка меню з обробкою подій клацання.


0

Спробуйте цей код

@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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.