android toolbar - Отключить гамбургер для анимации спины на панели инструментов




material design (7)

Очень легко реализовать Toolbar с гамбургером для анимации спины. По-моему, эта анимация бессмысленна, потому что, как и в случае с материальным дизайном, навигационный ящик закрывает Toolbar при открытии. Мой вопрос заключается в том, как правильно отключить эту анимацию и показать либо гамбургер, либо стрелку назад, используя getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Вот как я это сделал, но это выглядит как грязный хак:

mDrawerToggle.setDrawerIndicatorEnabled(false);

if (showHomeAsUp) {
    mDrawerToggle.setHomeAsUpIndicator(R.drawable.lib_ic_arrow_back_light);
    mDrawerToggle.setToolbarNavigationClickListener(view -> finish());
} else {
    mDrawerToggle.setHomeAsUpIndicator(R.drawable.lib_ic_menu_light);
    mDrawerToggle.setToolbarNavigationClickListener(view -> toggleDrawer());
}

Любые подсказки, как это должно быть правильно реализовано, чтобы использовать только setDisplayHomeAsUpEnabled для переключения между значками гамбургера и обратной стрелки?


Answers

По-моему, эта анимация бессмысленна

Ну, ActionBarDrawerToggle предназначен для анимирования.

Из документов:

Вы можете настроить анимированный переключатель, указав drawerArrowStyle в теме ActionBar.

Любые подсказки, как это должно быть правильно реализовано, чтобы использовать только setDisplayHomeAsUpEnabled для переключения между значками гамбургера и обратной стрелки?

ActionBarDrawerToggle - просто причудливый способ вызова ActionBar.setHomeAsUpIndicator . Таким образом, в любом случае вам нужно будет вызвать ActionBar.setDisplayHomeAsUpEnabled в true , чтобы отобразить его.

Если вы уверены, что вам нужно его использовать, я бы предложил просто вызвать ActionBarDrawerToggle.onDrawerOpened(View drawerView) и ActionBarDrawerToggle.onDrawerClosed(View drawerView) соответственно.

Это установит положение DrawerIndicator на 1 или 0 , переключение между стрелками и состояниями гамбургера DrawerArrowDrawable .

И в вашем случае нет необходимости даже прикреплять ActionBarDrawerToggle как DrawerLayout.DrawerListener . Как в:

mYourDrawer.setDrawerListener(mYourDrawerToggle);

Но гораздо более перспективный подход состоял бы в том, чтобы вызвать ActionBar.setHomeAsUpIndicator один раз и применить свой собственный значок гамбургера, вы также можете сделать это с помощью стиля. Затем, когда вы хотите отобразить обратную стрелку, просто вызовите ActionBar.setDisplayHomeAsUpEnabled и дайте AppCompat или инфраструктуре обработать остальные. Из комментариев, которые вы сделали, я уверен, что это то, что вы ищете.

Если вы не знаете, какой значок использовать, размер 24dp по умолчанию - 24dp , что означает, что вы захотите захватить ic_menu_white_24dp или ic_menu_black_24dp из значка навигации, установленного в официальном пакете официальных материалов Google.

Вы также можете скопировать DrawerArrowDrawable в свой проект и позволить затем переключаться со стрелками или гамбургерными состояниями по мере необходимости. Это самодостаточно, минус несколько ресурсов.


Отключение вызова ужина в onDrawerSlide() остановит анимацию между Arrow и Burger. Вы увидите только переключения (без анимации), когда ящик полностью открыт или полностью закрыт.

mActionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.open, R.string.closed) {
            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                  //super.onDrawerSlide(drawerView, slideOffset);
            }
        };
mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);

Если вы не хотите анимацию, не используйте ActionBarDrawerToggle . Вместо этого используйте код ниже.

toolbar.setNavigationIcon(R.drawable.ic_menu);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    drawer.openDrawer(GravityCompat.START);
                }
            });

Теперь есть выделенный метод для отключения анимации: toggle.setDrawerSlideAnimationEnabled(false)

Вот фрагмент, который я использую:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    [...]

    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    toggle.setDrawerSlideAnimationEnabled(false);
    drawer.addDrawerListener(toggle);
    toggle.syncState();
}

Это отключит анимацию при создании drawerToggle, переопределит onDrawerSlide ():

drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
        getToolbar(), R.string.open, R.string.close) {

    @Override
    public void onDrawerClosed(View view) {
        super.onDrawerClosed(view);
    }

    @Override
    public void onDrawerOpened(View drawerView) {
        super.onDrawerOpened(drawerView);
    }

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset) {
        super.onDrawerSlide(drawerView, 0); // this disables the animation 
    }
};

Если вы хотите полностью удалить стрелку, вы можете добавить

 super.onDrawerSlide(drawerView, 0); // this disables the arrow @ completed state

в конце функции onDrawerOpened.


Это моя функция для управления ActionBarDrawableToggle, расположенной в файле NavigationDrawerFragment, который я вызываю в обратном вызове onActivityCreated каждого фрагмента. функции почты. Значок гамбургера переходит в стрелку назад, а стрелка назад - нажата. Изменения ориентации корректно обрабатываются обработчиками.

...

import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;

...

public class NavigationDrawerFragment extends Fragment
{
    private ActionBarDrawerToggle mDrawerToggle;

    ...

    public void syncDrawerState()
    {
       new Handler().post(new Runnable()
        {
            @Override
            public void run()
            {
                final ActionBar actionBar = activity.getSupportActionBar();
                if (activity.getSupportFragmentManager().getBackStackEntryCount() > 1 && (actionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != ActionBar.DISPLAY_HOME_AS_UP)
                {
                    new Handler().post(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            mDrawerToggle.setDrawerIndicatorEnabled(false);
                            actionBar.setDisplayHomeAsUpEnabled(true);
                            mDrawerToggle.setToolbarNavigationClickListener(onToolbarNavigationClickListener());
                        }
                    });
                } else if (activity.getSupportFragmentManager().getBackStackEntryCount() <= 1 && (actionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) == ActionBar.DISPLAY_HOME_AS_UP)
                {
                    actionBar.setHomeButtonEnabled(false);
                    actionBar.setDisplayHomeAsUpEnabled(false);
                    mDrawerToggle.setDrawerIndicatorEnabled(true);
                    mDrawerToggle.syncState();
                }
            }
        });      
    }
}

Это только мой метод onActivityCreated в моем базовом фрагменте.

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);
    navigationDrawerFragment.syncDrawerState();
}

Нынешний ответ очень хорош и помог мне привести меня к собственному решению. Есть несколько причин, по которым я решил опубликовать собственное решение, хотя этот вопрос уже имеет правильный ответ:

  • Я работаю в Котлине, а не на Яве. Люди, которые оказываются с одинаковой проблемой, должны будут перевести текущее решение.
  • Я хотел написать ответ, который был более разборчивым, чтобы люди могли легче адаптировать его к своим собственным проблемам.
  • Как было предложено dengue8830, я инкапсулировал решение этой проблемы в класс, поэтому любой может использовать, даже не беспокоясь о реализации.

Чтобы использовать его, просто сделайте что-нибудь вроде:

  • DateInputMask (mEditText) .listen ()

И решение показано ниже:

class DateInputMask(val input : EditText) {

    fun listen() {
        input.addTextChangedListener(mDateEntryWatcher)
    }

    private val mDateEntryWatcher = object : TextWatcher {

        var edited = false
        val dividerCharacter = "/"

        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
            if (edited) {
                edited = false
                return
            }

            var working = getEditText()

            working = manageDateDivider(working, 2, start, before)
            working = manageDateDivider(working, 5, start, before)

            edited = true
            input.setText(working)
            input.setSelection(input.text.length)
        }

        private fun manageDateDivider(working: String, position : Int, start: Int, before: Int) : String{
            if (working.length == position) {
                return if (before <= position && start < position)
                    working + dividerCharacter
                else
                    working.dropLast(1)
            }
            return working
        }

        private fun getEditText() : String {
            return if (input.text.length >= 10)
                input.text.toString().substring(0,10)
            else
                input.text.toString()
        }

        override fun afterTextChanged(s: Editable) {}
        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
    }
}






android material-design android-toolbar