Java Android 上的导航抽屉滞后

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25534806/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:35:31  来源:igfitidea点击:

Navigation Drawer lag on Android

javaandroidnavigation-drawerfragmenttransaction

提问by AND4011002849

I'm having a problem with Navigation Drawer , it is too slow, the solution I'm looking for is to close the drawer first and then show the activity, but It is not working, certainly I'm missing something.

我的 Navigation Drawer 有问题,它太慢了,我正在寻找的解决方案是先关闭抽屉,然后显示活动,但它不起作用,当然我遗漏了一些东西。

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

    }

采纳答案by Yuraj

You can do It this way to avoid drawer lag, change your onItemClick:

您可以通过这种方式避免抽屉延迟,更改您的onItemClick

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

Edit:prefered way should be setting DrawerListener on DrawerLayout and setting your fragment in onDrawerClosedlike this:

编辑:首选方式应该是在 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;
          }
        }
    });

回答by uDevel

Rather than do transaction in onClick, why not do it in onDrawerClosed from DrawerLayout.DrawerListener?

与其在 onClick 中进行交易,为什么不在 DrawerLayout.DrawerListener 中的 onDrawerClosed 中进行交易呢?

回答by Azizi Musa

Try this. The drawer will be told to close using broadcast. This is to ensure, the activity or fragment being load is done 1st, before closing the drawer.

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

Inside MainActivity

在 MainActivity 内部

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

Inside activity or fragment

内部活动或片段

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

you could change it to earlier process from onCreate or onAttach, but it depend on your app.

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

回答by Quentin G.

I think I have found the best solution for this !

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

First do your fragment transaction like so :

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

new Handler().post(new Runnable() {
                @Override
                public void run() {
                    getSupportFragmentManager()
                            .beginTransaction()
                            .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
                            .replace(R.id.container, finalMenuFragment)
                            .commit();
                }
            });

I know it looks useless to post a Runnable but this hack avoid lag on the click animation on the drawer especially when you use android:background="?attr/selectableItemBackground"for a clickable element.

我知道发布 Runnable 看起来没用,但是这个 hack 避免了抽屉上点击动画的延迟,尤其是当你使用 android:background="?attr/selectableItemBackground"可点击元素时。

And then you close the drawer AT THE END OF THE onResume() function of your fragment (in this example it's "finalMenuFragment") like so :

然后在片段的 onResume() 函数的结尾处关闭抽屉(在本例中为“finalMenuFragment”),如下所示:

 new Handler().post(new Runnable() {
        public void run() {

            mDrawerLayout.closeDrawer(mFragmentContainerView);
        }
    });

Again I know it seems stupid to post a Runnable but it makes the close animation smooth.

我再次知道发布 Runnable 似乎很愚蠢,但它使关闭动画变得流畅。

This way, the drawer will close as fast as it can if you want smooth animations and if your fragment has not a lot of views in it, it will close faster and still without lag.

这样,如果您想要流畅的动画,并且您的片段中没有很多视图,则抽屉将尽可能快地关闭,它会更快地关闭并且仍然没有延迟。

I would like some feedback on this if somebody tested this solution, hope it helps !

如果有人测试了此解决方案,我希望对此提供一些反馈,希望对您有所帮助!

回答by Deividas Strioga

I think using delays for fragment transactions is the most unstable solution.

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

The one with doing them onDrawerClosed gives you a slight lag between closing and fragment appearing.

在 DrawerClosed 上执行它们的方法会让您在关闭和片段出现之间有一点延迟。

I prefer doing transaction straight after navigation click, close the drawer after with postDelayed 200ms (in runnable check just in case it is not null). The fragment opens just before drawer starts closing.

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

Not only delay from tap until drawer closing is shorter than the one after drawer closed and next fragment appearing, it is better UX as user is removing finger from screen - delay is less apparent.

不仅从点击到抽屉关闭的延迟比在抽屉关闭和下一个片段出现之后的延迟更短,而且当用户从屏幕上移开手指时它是更好的 UX - 延迟不那么明显。

回答by Darshan

I just Solved this issue in just One-Line

我刚刚在One-Line 中解决了这个问题

go to your Menifestfile In your drawer Activity just put HardwareAccelerated trueto prevent lag of opening drawer

转到您的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" />

回答by sajad abbasi

If it lags you can request for hardware acceleration. if manifest add this to your activity

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

 android:hardwareAccelerated="true"

if your oncreate method add this code

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

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

now you have hardware acceleration in your activity. source: https://developer.android.com/guide/topics/graphics/hardware-accel.html

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

回答by GouravGupta

well, you can delay for few seconds before closing the drawer!

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

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

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

Worked for me!

为我工作!