如何使用导航抽屉打开和关闭更改按钮图像

Posted

技术标签:

【中文标题】如何使用导航抽屉打开和关闭更改按钮图像【英文标题】:How do I change my button image with navigation drawer opening and closing 【发布时间】:2013-12-13 07:26:55 【问题描述】:

我的导航片段有一个导航按钮,该按钮变为活动状态并在单击时打开一个导航抽屉菜单:

现在,当我单击它时,它会变为活动状态,如下所示:

但是,我想将它与导航抽屉相关联,这样,即使我没有单击按钮并滑动打开导航抽屉,当导航抽屉菜单打开时,按钮也会在通过滑动关闭时变为活动状态从右到左返回,按钮变为红色/无效。我正在尝试使用的代码如下:

private boolean mIsNavigationOpen = false;
    private DrawerLayout drawerLayout;
    private NavigationPanelFragment dlDrawer;
    private ActionBarDrawerToggle actionBarDrawerToggle;
public boolean isNavigationOpen() 

        return mIsNavigationOpen;

    
//----------Code for Navigation open logo button active/inactive instances
    @SuppressWarnings("deprecation")
    public void setNavigationOpen(final boolean isNavigationOpen) 
        this.mIsNavigationOpen = isNavigationOpen;
        final ImageButton mainButton = (ImageButton) findViewById(R.id.button_main);
        if(isNavigationOpen) 
            mainButton.setBackgroundResource(R.drawable.bg_helios_active);
         else 
            mainButton.setBackgroundDrawable(null);
        
@Override
    protected void onCreate(final Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        //----------Code for Navigation Drawer setup
        // 2. App Icon 
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        // 2.1 create ActionBarDrawerToggle
                 actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
                            R.drawable.arrow_up, R.string.drawer_open, R.string.drawer_close)

                        /** Called when a drawer has settled in a completely closed state. */
                        public void onDrawerClosed(View view) 
                           // getActionBar().setTitle(NavigationPanelFragment.activeFragmentTitle);
                           // invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                        

                        /** Called when a drawer has settled in a completely open state. */
                        public void onDrawerOpened(View drawerView) 
                         //   getActionBar().setTitle(NavigationPanelFragment.activeFragmentTitle);
                          //  invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                        
                    ;


                // 2.2 Set actionBarDrawerToggle as the DrawerListener
                drawerLayout.setDrawerListener(actionBarDrawerToggle);
          
@Override
    protected void onPostCreate(Bundle savedInstanceState) 
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
         actionBarDrawerToggle.syncState();
    
private void setupOnClickListenerForMainButton() 
        final ImageButton mainButton = (ImageButton) findViewById(R.id.button_main);
        mainButton.setOnClickListener(new OnClickListener() 

            @Override
            public void onClick(final View v) 
                toggleNavigationPanel();


            
        );
    
@Override
    public boolean onMenuItemSelected(final int featureId, final MenuItem item) 
        switch (item.getItemId()) 
            case android.R.id.home:
                toggleNavigationPanel();
                break;

            default:
                break;
        
        return super.onMenuItemSelected(featureId, item);
    
public void onNewsClicked(final View view) 
        if(mIsNavigationOpen) 
            toggleNavigationPanel();
        

        if (isFragmentVisible(NewsFragment.TAG_NEWS_FRAGMENT)) 
            return;
        

        FragmentStackManager.getInstance().clearBackStack(getSupportFragmentManager());
        mActiveFragment = NewsFragment.newInstance(getSupportFragmentManager());
        updateActionBarTitle();
        //For swipe action close drawer on button click
         drawerLayout.closeDrawer(R.id.drawer);
    
public void onListsClicked(final View view) 
        if(mIsNavigationOpen) 
            toggleNavigationPanel();
        

        if (isFragmentVisible(ListsContainerFragment.TAG_LIST_CONTAINER_FRAGMENT)) 
            return;
        

        FragmentStackManager.getInstance().clearBackStack(getSupportFragmentManager());
        mActiveFragment = ListsContainerFragment.newInstance(getSupportFragmentManager());
        updateActionBarTitle();
        //For swipe action close drawer on button click
        drawerLayout.closeDrawer(R.id.drawer);
    
private void toggleNavigationPanel() 
        //final FragmentStackManager manager = FragmentStackManager.getInstance();
        if (mIsNavigationOpen) 
            //NavigationPanelFragment.removeInstance(getSupportFragmentManager());
            updateActionBarTitle();
            drawerLayout.closeDrawer(R.id.drawer);
         else 
            drawerLayout.openDrawer(R.id.drawer);
            final TextView title = (TextView) findViewById(R.id.main_title);
            title.setText(getString(R.string.title_applications));
            //NavigationPanelFragment.newInstance(getSupportFragmentManager(), manager.getTopTitle());
        


        setNavigationOpen(!mIsNavigationOpen);
    

您可能希望专注于 main_button 和 togglenavigationpanel。我添加了条件 if(drawerlayout.isdraweropen(R.id.drawer))closedrawerlayout... 但它没有成功。我想知道是否有人对此有任何想法?

谢谢!

【问题讨论】:

你为什么不使用onDrawerClosedonDrawerOpened 如何使用它?能用代码说明一下吗? 另外,我添加了 public void onDrawerClosed(View view) toggleNavigationPanel()public void onDrawerOpened(ViewdrawerView) toggleNavigationPanel() 它适用于滑动但 onclick 它因空指针异常而崩溃 【参考方案1】:

当您设置抽屉时,添加了一个侦听器,该侦听器具有当抽屉处于任一最终状态时的回调,因此您需要做的是在这些回调中重置可绘制对象。我已经展示了我认为你的最终代码应该是什么样子,减去你需要做的一些清理工作,希望它有所帮助

private DrawerLayout drawerLayout;
private NavigationPanelFragment dlDrawer;
private ActionBarDrawerToggle actionBarDrawerToggle;
private ImageButton mDrawerButton; //Store it! - findViewById is *Expensive*
private TextView mTitle;

@Override
protected void onCreate(final Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);
    mTitle = (TextView) findViewById(R.id.main_title);
    mDrawerButton = (ImageButton) findViewById(R.id.button_main);
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
            R.drawable.arrow_up, R.string.drawer_open, R.string.drawer_close) 

        public void onDrawerClosed(View view) 
            mDrawerButton.setImageResource(R.drawable.bg_helios_inactive);
        

        public void onDrawerOpened(View drawerView) 
            mDrawerButton.setImageResource(R.drawable.bg_helios_active);
        

    ;
    drawerLayout.setDrawerListener(actionBarDrawerToggle);
    setupOnClickListenerForMainButton(;


@Override //Note: I'd imagine this should be in onResume ...
protected void onPostCreate(Bundle savedInstanceState) 
    super.onPostCreate(savedInstanceState);
    actionBarDrawerToggle.syncState();


private void setupOnClickListenerForMainButton() 
    mDrawerButton.setOnClickListener(new OnClickListener() 
        @Override
        public void onClick(final View v) 
            toggleNavigationPanel();
        
    );


...

private void toggleNavigationPanel() 
    //if ( drawerLayout.isOpen() )  //I dont know what methods these objects have
    if ( dlDrawer.isOpen() )  //but one of these must be sensibly storing its own state
        updateActionBarTitle();
        drawerLayout.closeDrawer(R.id.drawer);
     else 
        drawerLayout.openDrawer(R.id.drawer);
        mTitle.setText(getString(R.string.title_applications));
    

【讨论】:

它似乎在 mDrawerButton.setImageResource(R.drawable.bg_helios_active);有一个空指针异常。但是,当我回到我的原始实现并在 Oncreate 的 onDrawerOpened/Ondrawerclosed 中添加 toggleNavigationPanel() 时,它确实识别了导航抽屉的滑动并将 helios 按钮切换为选中和取消选中,但只要我点击 helios button ,它崩溃了一个空指针异常,我想知道是什么导致了崩溃 如果您在由 toggleNavigationPanel() 的操作触发的回调中有 toggleNavigationPanel(),它将如何工作?确保在 oncreate (mDrawerButton) 中找到图像视图并查看您的 logcat 以获取更多信息 我也需要为按钮的点击保留 isNavigationOpen() 函数,所以我将条件定义为 if ( isNavigationOpen() ||drawerLayout.isDrawerOpen(R.id.drawer) ) updateActionBarTitle();抽屉布局.closeDrawer(R.id.drawer); else 抽屉布局.openDrawer(R.id.drawer); mTitle.setText(getString(R.string.title_applications)); ? 保留该变量是自找麻烦,因为抽屉应该知道它的状态,然后您还要存储一个单独的状态表示,这可能会不同步。使用(或在必要时添加)抽屉状态和 isDrawerOpen 方法。 drawLayout.closeDrawer 和 openDrawer 应该更新状态,因此绝对没有理由将其存储在这里,脱离上下文 即使我更改所有内容并将任何内容放在 public void onDrawerClosed(View view) 中,它也会在 android.support.v4.widget.DrawerLayout.updateDrawerState(DrawerLayout.java:459) 处因空指针异常而崩溃在 android.support.v4.widget.DrawerLayout$ViewDragCallback.onViewDragStateChanged(DrawerLayout.java:1348) 在 android.support.v4.widget.ViewDragHelper.setDragState(ViewDragHelper.java:866) 在 android.support.v4.widget.ViewDragHelper $2.run(ViewDragHelper.java:335) 在 android.os.Handler.handleCallback(Handler.java:615) 在 android.os.Handler.dispatchMessage(Handler.java:92)

以上是关于如何使用导航抽屉打开和关闭更改按钮图像的主要内容,如果未能解决你的问题,请参考以下文章

如何默认导航抽屉在移动设备上关闭并在桌面上打开?

当按下后退按钮并打开导航抽屉时,我的应用程序关闭而不是关闭抽屉

如何打开关闭应用程序后打开的最后一个片段并使用导航抽屉和导航组件重新打开它

将(打开/关闭)按钮添加到(打开/关闭)导航抽屉的活动

如何在主片段中单击按钮时打开导航抽屉?

如何取消在颤动中打开和关闭导航抽屉的动画?