【问题标题】:how to create smooth navigation drawer如何创建流畅的导航抽屉
【发布时间】:2013-09-18 12:01:24
【问题描述】:

我正在使用this 示例作为导航抽屉。单击左侧抽屉列表视图的项目时,它会显示一些图像,但抽屉布局关闭不顺畅。

单击listview的项目后,我应该在这里做什么才能顺利关闭左侧抽屉布局。

【问题讨论】:

标签: android navigation-drawer


【解决方案1】:

不确定这是不是最好的方法,但我解决这个问题的方法是创建一个在 onDrawerClosed 中运行的待处理 Runnable。例如:

private void selectItem(final int position) {
    mPendingRunnable = new Runnable() {
        @Override
        public void run() {
            // update the main content by replacing fragments
            Fragment fragment = new PlanetFragment();
            Bundle args = new Bundle();
            args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
            fragment.setArguments(args); 

            FragmentManager fragmentManager = getFragmentManager();
            fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
        }
    });

    // update selected item and title, then close the drawer
    mDrawerList.setItemChecked(position, true);
    setTitle(mPlanetTitles[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
}

@Override
public void onDrawerClosed(View view) {
    getActionBar().setTitle(mTitle);
    invalidateOptionsMenu();

    // If mPendingRunnable is not null, then add to the message queue 
    if (mPendingRunnable != null) {
        mHandler.post(mPendingRunnable);
        mPendingRunnable = null;
    }
}

【讨论】:

  • 请问,你从哪里得到mHandler?我正在尝试在 C# 中执行此操作,但我对它的来源感到困惑。
  • @ChaseFlorell 只需创建一个成员变量。例如。 Handler mHandler = new Handler();
  • 我想补充一下:由于在启动您的应用程序时不会调用onDrawerClosed(),因此您还应该在onCreate()末尾发布mPendingRunnablemHandler
  • 您可以在selectItem 中执行onDrawerClosed 中的所有操作。最新版本的 Gmail 就是这样做的。
  • 别忘了在Activity中实现DrawerLayout.DraweListener并设置监听器:drawer.setDrawerListener(this);
【解决方案2】:

完美运行

private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
            mDrawerLayout.closeDrawer(mDrawerList);
            mDrawerLayout.postDelayed(new Runnable() {
                @Override
                public void run() {
                    selectItem(position);
                }
            }, 300);
        }
    }

【讨论】:

  • @Ewoks 不幸的是,如果您不想要一个生涩的关闭动画,那么在加载下一个片段/活动之前创建人为延迟似乎是唯一的解决方案。
  • @mattblang Paul 给出了更好的解决方案
  • 如此美妙的sn-p
【解决方案3】:

只需使用处理程序将drawerLayout.closeDrawer() 发布到消息队列上,以最小的延迟解决了我的问题。 Handler.postDelayed() 是这里的关键。

 public void selectItem(int position)
    {
        switch (position)
        {
            case 0:

                DashboardFragment dashboardFragment = new DashboardFragment();
                Bundle args = new Bundle();
                args.putInt(dashboardFragment.ARG_SCREEN_NUMBER, position);
                dashboardFragment.setArguments(args);

                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

                // Replace whatever is in the fragment_container view with this fragment,
                // and add the transaction to the back stack so the user can navigate back
                transaction.replace(R.id.fragmentLayout, dashboardFragment, TAG_DASHBOARD);
                transaction.addToBackStack(null);

                // Commit the transaction
                transaction.commit();
                getSupportFragmentManager().executePendingTransactions();
                break;            

            default:
                break;

        }

        // Highlight the selected item, update the title, and close the drawer
        drawerList.setItemChecked(position, true);
        setTitle(mScreenTitles[position]);

        mPendingRunnable = new Runnable()
        {
            @Override
            public void run()
            {
                drawerLayout.closeDrawer(GravityCompat.START);
            }
        };
        mHandler.postDelayed(mPendingRunnable,50);

    }

【讨论】:

    【解决方案4】:

    我不使用线程,因为我需要在关闭导航菜单后更新 UI。

    以下代码对我有用。

    我使用fragment作为类的成员变量来更新ui

    setFragment() 函数用于将片段分配给片段变量

    在 onDrawerClosed() 事件中,我更新了 ui。

    mDrawerList.setOnItemClickListener(new ListView.OnItemClickListener()
    {
       @Override
       public void onItemClick(AdapterView<?> parent, View view, int position, long id)
       {
           setFragment(position);
       }
    });
    
    
    // for getting fragment
    protected void setFragment(int p)
    {
        fragment = null;
    
        switch (position)
        {
            case 1:
                fragment = new DashboardFragment();                
                break;
        }
    
        if (fragment != null)
        {
            mDrawerList.setItemChecked(position, true);
            mDrawerList.setSelection(p);
            mDrawerLayout.closeDrawer(mDrawerList);
        }
    }
    
    
    // on close draw , fragment is loaded on screen
    public void onDrawerClosed(View view)
    {
       getSupportActionBar().setTitle(mTitle);
       invalidateOptionsMenu();
    
       FragmentManager fragmentManager = getSupportFragmentManager();
    
       fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
    }
    

    【讨论】:

      【解决方案5】:

      请查看我的 MainActivity 以使用自定义 topBar 布局制作流畅的 DrawerLayout(打开/关闭)。

      public class MainActivity extends BaseActivity
          implements NavigationView.OnNavigationItemSelectedListener {
      
      Fragment fragment = null;
      Class fragmentClass = null;
      FrameLayout frameLayout;
      TextView topTilte;
      DrawerLayout drawer;
      NavigationView navigationView;
      private boolean isDrawerOpen = false;
      
      @Override
      protected void onCreateFinished() {
          setContentView(R.layout.activity_main);
      
          drawer = findViewById(R.id.drawer_layout);
          navigationView = findViewById(R.id.nav_view);
      
          topTilte = findViewById(R.id.toolbar_title);
          fragmentClass = HomeFragment.class;
          topTilte.setText(R.string.menu_home);
          setFragment();
      
          drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
              @Override
              public void onDrawerSlide(@NonNull View view, float slideOffset) {
                  if(slideOffset > .55 && !isDrawerOpen){
                      onDrawerOpened(view);
                      isDrawerOpen = true;
                  } else if(slideOffset < .45 && isDrawerOpen) {
                      onDrawerClosed(view);
                      isDrawerOpen = false;
                  }
              }
      
              @Override
              public void onDrawerOpened(@NonNull View view) {
      
              }
      
              @Override
              public void onDrawerClosed(@NonNull View view) {
      
              }
      
              @Override
              public void onDrawerStateChanged(int i) {
      
              }
          });
      
          navigationView.setNavigationItemSelectedListener(this);
      }
      
      @Override
      protected void afterInjection() {
      
      }
      
      public void openMenu(View v) {
          drawer.openDrawer(Gravity.LEFT);
      }
      
      @Override
      public void onBackPressed() {
          DrawerLayout drawer = findViewById(R.id.drawer_layout);
          if (drawer.isDrawerOpen(GravityCompat.START)) {
              drawer.closeDrawer(GravityCompat.START);
          } else {
              super.onBackPressed();
          }
      }
      
      @SuppressWarnings("StatementWithEmptyBody")
      @Override
      public boolean onNavigationItemSelected(MenuItem item) {
          // Handle navigation view item clicks here.
          int id = item.getItemId();
          if (id == R.id.nav_home) {
              topTilte.setText(R.string.menu_home);
              fragmentClass = HomeFragment.class;
              setFragment();
      
          } else if (id == R.id.nav_profile) {
      
          } 
      
          return true;
      }
      
      private void setFragment() {
      
      
          final Handler handler = new Handler();
          handler.postDelayed(new Runnable() {
              @Override
              public void run() {
                  try {
                      fragment = (Fragment) fragmentClass.newInstance();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
      
                  FragmentManager fragmentManager = getSupportFragmentManager();
                  fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
      
                  drawer.closeDrawer(GravityCompat.START);
              }
          }, 200);
      }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-12-14
        • 1970-01-01
        • 2020-03-29
        • 1970-01-01
        • 2021-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多