[英]Navigation drawer lags in Android when opening or closing fragment in Android
[英]Navigation drawer lags when opening and closing android
我试图让我的导航抽屉顺利运行,因为在打开和关闭抽屉时过渡时会出现卡顿/延迟。 我希望它能完美运行。 有什么帮助吗?
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final MediaPlayer mp = MediaPlayer.create(this, R.raw.firsteps);
mp.start();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setItemIconTintList(null);
navigationView.setNavigationItemSelectedListener(this);
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().replace(R.id.content_frame, new MainFragment()).commit();
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
startActivity(new Intent(getApplicationContext(),Testing.class));
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
//final MediaPlayer mp = MediaPlayer.create(this, R.raw.xlophone);
FragmentManager fm = getSupportFragmentManager();
int id = item.getItemId();
if (id == R.id.car_stories) {
fm.beginTransaction().replace(R.id.content_frame,new ChildrensList()).commit();
//mp.start();
} else if (id == R.id.car_places) {
fm.beginTransaction().replace(R.id.content_frame,new ImportFragment()).commit();
//mp.start();
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
文档: 点击
尝试这个:
//使用Handler()。postDelayed
@Override
public boolean onNavigationItemSelected(MenuItem item) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
switch (item.getItemId()) {
case: R.id.example1:
// do something
break;
case: R.id.example2:
// do something
break;
default: // do something
}
}, 200);
drawer.closeDrawer(GravityCompat.START);
return true;
}
以我的拙见,您需要避免每次点击都称为“新”。
为了解决这个问题,您可以使用常量值来导航抽屉的android:layout_width
和android:layout_height
属性,即。
android:layout_width="@dimen/navigation_drawer_width"
android:layout_height="match_parent"
您可能还想对AndroidManifest.xml
活动启用硬件加速
<activity
android:name=".ui.SomeActivity"
android:hardwareAccelerated="true" />
滞后是由于在同一线程(主线程或UI线程)中发生两次繁重的操作(片段替换和抽屉动画)引起的。
解决此问题的一种方法是在抽屉完全关闭后调用碎片更换。 这样,这两个操作将不会同时发生。
另外,将片段容器与进度条交叉淡入淡出是一个不错的设计实现。
在您的Activity
您应该具有以下内容:
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Show progress bar and hide content container
crossfade(progressBar, container, false)
drawerLayout?.addDrawerListener(object : DrawerLayout.DrawerListener {
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}
override fun onDrawerOpened(drawerView: View) {}
override fun onDrawerStateChanged(newState: Int) {}
override fun onDrawerClosed(drawerView: View) {
// This method will be called after drawer animation finishes
// Perform the fragment replacement
when (item.itemId) {
R.id.drawer_item_1 -> {
supportFragmentManager.beginTransaction()
.replace(R.id.container, MyFragmentOne.newInstance())
.addToBackStack(null)
.commit()
}
R.id.drawer_item_2 -> {
supportFragmentManager.beginTransaction()
.replace(R.id.container, MyFragmentTwo.newInstance())
.addToBackStack(null)
.commit()
}
}
// Cross fade back the content container and hide progress bar
crossfade(container, progressBar, false)
// Remove this listener so close by, for example, swiping do not call it again
drawerLayout.removeDrawerListener(this)
}
})
// Closes the drawer, triggering the listener above
drawerLayout.closeDrawer(GravityCompat.START)
return true
}
private fun crossfade(viewIn: View, viewOut: View, animateViewOut: Boolean = true) {
val crossfadeDuration = 200L
// Set the content view to 0% opacity but visible, so that it is visible
// (but fully transparent) during the animation.
viewIn.alpha = 0f
viewIn.visibility = View.VISIBLE
viewIn.bringToFront()
// Animate the in view to 100% opacity, and clear any animation
// listener set on the view.
viewIn.animate()
.alpha(1f)
.setDuration(crossfadeDuration)
.setListener(null)
// Animate the out view to 0% opacity. After the animation ends,
// set its visibility to GONE as an optimization step (it won't
// participate in layout passes, etc.)
viewOut.animate()
.alpha(0f)
.setDuration(if (animateViewOut) crossfadeDuration else 0)
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
viewOut.visibility = GONE
}
})
}
在您的xml中,您应该具有以下内容:
...
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:openDrawer="start">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/drawer" />
</android.support.v4.widget.DrawerLayout>
....
只需延迟关闭抽屉,即可顺利关闭 animation
navigation.setNavigationItemSelectedListener { menuItem ->
// make closing side-menu smooth
Completable.timer(100, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
.subscribe {
drawer.closeDrawer(GravityCompat.START)
}.addTo(disposable)
when(menuItem.itemId){
R.id.sideMenuDashboard ->
navController.navigate(R.id.fragment1)
R.id.sideMenuProfile ->
navController.navigate(R.id.fragment2)
}
true
}
调用抽屉布局.closeDrawers()之后,创建一个新线程
new Thread(new Runnable() {
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(300);
//Here call you fragmentManager
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
当然,您可以根据需要改变MILISECONDS。 对不起我的英语
滞后是由于在同一线程(主线程或UI线程)中发生两次繁重的操作(片段替换和抽屉动画)引起的。
在我的情况下,导航标题背景图片的尺寸很大,因此它可以在高性能设备上使用,但在低性能设备上却无法使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.