导航抽屉在Android上滞后

时间:2014-08-27 18:45:21

标签: java android navigation-drawer fragmenttransaction

我对导航抽屉有问题,它太慢了,我要找的解决方法是首先关闭抽屉然后显示活动,但它不起作用,当然我&# 39;我缺少一些东西。

private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int posicao, long id) {
            setLastPosition(posicao);
            setFragmentList(lastPosition);
            layoutDrawer.closeDrawer(linearDrawer);
        }
    }

    private OnClickListener userOnClick = new OnClickListener() {
        @Override
        public void onClick(View v) {
            layoutDrawer.closeDrawer(linearDrawer);
        }
    };

    private void setFragmentList(int posicao) {

        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment fragment = new FragmentViagens();

        switch (posicao) {

            case 0:
                fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
                break;
            case 1:
                fragmentManager.beginTransaction().replace(R.id.content_frame, new FragmentPedidos()).commit();
                break;
            case 2:
                fragmentManager.beginTransaction().replace(R.id.content_frame, new FragmentClientes()).commit();
                break;

        }

        navigationAdapter.setChecked(posicao, true);
        setTitleFragments(lastPosition);
        navigationAdapter.resetarCheck();
        layoutDrawer.closeDrawer(linearDrawer);

    }

9 个答案:

答案 0 :(得分:35)

你可以这样做以避免抽屉滞后,改变 onItemClick

layoutDrawer.closeDrawer(linearDrawer);
setLastPosition(posicao);
new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            setFragmentList(lastPosition);
        }
    }, 200);

编辑:首选方式应该是在DrawerLayout上设置DrawerListener并在onDrawerClosed中设置您的片段 像这样:

Fragment mFragmentToSet = null;

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    // Handle navigation view item clicks here.
    switch (item.getItemId()) {
        case R.id.nav_home:
            mFragmentToSet = HomeFragment.newInstance(); 
            break;
    }

    mDrawerLayout.closeDrawer(GravityCompat.START);
    return true;
}

mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
        @Override public void onDrawerSlide(View drawerView, float slideOffset) {}
        @Override public void onDrawerOpened(View drawerView) {}
        @Override public void onDrawerStateChanged(int newState) {}

        @Override
        public void onDrawerClosed(View drawerView) {
          //Set your new fragment here
          if (mFragmentToSet != null) {
            getSupportFragmentManager()
                  .beginTransaction()
                  .replace(FRAGMENT_CONTAINER_ID, mFragmentToSet)
                  .commit();
            mFragmentToSet = null;
          }
        }
    });

答案 1 :(得分:18)

不是在onClick上做事务,为什么不在DrawerLayout.DrawerListener的onDrawerClosed中做呢?

答案 2 :(得分:7)

我想我找到了最好的解决方案!

首先像你这样做你的片段交易:

android:background="?attr/selectableItemBackground"

我知道发布Runnable看起来没什么用处,但这个hack避免了抽屉上点击动画的延迟,尤其是当你使用时 new Handler().post(new Runnable() { public void run() { mDrawerLayout.closeDrawer(mFragmentContainerView); } }); 表示可点击的元素。

然后你关闭你的片段的onResume()函数的抽屉(在这个例子中它是&#34; finalMenuFragment&#34;),如下所示:

 In[]: foo = ['a', 'b', 'c']
 In[]: [x for x in itertools.something(foo)]
Out[]: 
       [('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]

我再次发现发布Runnable似乎很愚蠢,但它使得近距离动画变得平滑。

这样,如果您想要平滑的动画,抽屉会尽可能快地关闭,如果您的片段中没有很多视图,它会更快地关闭并且仍然没有滞后。

如果有人测试了这个解决方案,我希望得到一些反馈,希望它有所帮助!

答案 3 :(得分:5)

我刚刚在 One-Line

中解决了这个问题

转到 Menifest 文件在您的抽屉活动中,只需将 HardwareAccelerated true 设置为防止打开抽屉滞后

<activity
        android:name=".activity.YourDrawerActivity"
        android:configChanges="keyboardHidden|orientation"
        android:screenOrientation="portrait"
        android:hardwareAccelerated="true"  //important 
        android:theme="@style/AppTheme.NoActionBar"
        android:windowSoftInputMode="stateHidden" />

答案 4 :(得分:3)

如果滞后,您可以请求硬件加速。 如果清单将此添加到您的活动

 android:hardwareAccelerated="true"

如果您的oncreate方法添加此代码

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

现在您的活动中有硬件加速。 来源:https://developer.android.com/guide/topics/graphics/hardware-accel.html

答案 5 :(得分:1)

试试这个。抽屉将被告知使用广播关闭。这是为了确保在关闭抽屉之前,首先完成装载的活动或片段。

内部主要活动

private BroadcastReceiver xBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Drawer.isDrawerOpen(GravityCompat.START)){
            Drawer.closeDrawers();
        }
    }
};

@Override
protected void onStart() {
    super.onStart();
    IntentFilter filter = new IntentFilter();
    filter.addAction("my.drawer.listener");
    this.registerReceiver(xBroadcastReceiver, filter);
}

@Override
public void onDestroy() {
    super.onDestroy();
    this.unregisterReceiver(xBroadcastReceiver);
}

内部活动或片段

@Override
public void onStart() {
    super.onStart();
    Intent intent = new Intent();
    intent.setAction("my.drawer.listener");
    getActivity().sendBroadcast(intent);
}

您可以将其从onCreate或onAttach更改为早期流程,但这取决于您的应用。

答案 6 :(得分:0)

我认为使用片段事务的延迟是最不稳定的解决方案。

在onDrawerClosed上执行它们的那个会让你在关闭和片段出现之间略有延迟。

我更喜欢在导航点击后直接进行交易,在postDelayed 200ms之后关闭抽屉(在runnable检查中以防它不为空)。 片段在抽屉开始关闭之前打开。

不仅从抽头到抽屉关闭的延迟比抽屉关闭和下一个片段出现之后的延迟更短,因此用户将手指从屏幕上移开是更好的用户体验 - 延迟不太明显。

答案 7 :(得分:0)

好吧,您可以在关闭抽屉前延迟几秒钟!

`new Handler().postDelayed(new Runnable() {
       @Override
          public void run() {

               mDrawerLayout.closeDrawer(containerView)
          }
   }, 300)`

为我工作!

答案 8 :(得分:0)

请注意,当您的实现无法正确处理方案时,您的OnBackpressed()方法将无法正常运行,因为其中有些人正在经历这种情况。

算法

  1. 声明一个类变量,以检查何时选择了导航项。如果选择了一项,则为该变量分配 true ,并在导航后将变量设置为 false

  2. 在您的课程中实施 NavigationView.OnNavigationItemSelectedListener ,并通过 onNavigationItemSelected()方法处理导航。请注意,为防止滞后,请在您的 onNavigationItemSelected()方法中添加 DrawerListener(),最后使用 onDrawerClosed()方法处理导航您的 DrawerListener()

这样,您的片段或活动将仅在成功关闭抽屉后打开,这将防止意外拖延。

Java代码实现。

 public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

   private static boolean itemSelected;

   NavigationView navigationView;

   DrawerLayout drawer;


@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);


    itemSelected =false;

    NavigationView navigationView = findViewById(R.id.your_navigation_view_id);

    DrawerLayout drawer = findViewById(R.id.your_drawer_id);


    }


@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {

    itemSelected = true;

    drawer.closeDrawer(GravityCompat.START);

    drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
        @Override
        public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {

        }

        @Override
        public void onDrawerOpened(@NonNull View drawerView) {

        }

        @Override
        public void onDrawerClosed(@NonNull View drawerView) {

            if(itemSelected) {

                if (item.getItemId() == R.id.profile_menu) {

                  //Open your Activity or Fragment here
                  startActivity(new Intent(MainActivity.this, ProfileActivity.class));

                } else if (item.getItemId() == R.id.nav_services_menu) {
           
                  //Open your Activity or Fragment here
                  startActivity(new Intent(MainActivity.this, Services.class));

              }

                itemSelected = false;

            }

        }

        @Override
        public void onDrawerStateChanged(int newState) {

        }
    });

    return true;

  }

}