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
Navigation Drawer lag on Android
提问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 onDrawerClosed
like 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!
为我工作!