简体   繁体   English

导航抽屉在打开和关闭时滞后 android

[英]Navigation drawer lags when opening and closing android

I am at trying to to get my navigation drawer to run smoothly as there is a stutter/delay in transition when opening and closing the drawer.我试图让我的导航抽屉顺利运行,因为在打开和关闭抽屉时过渡时会出现卡顿/延迟。 I would like this to run perfectly.我希望它能完美运行。 Any help?有什么帮助吗?

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

Documentation: Click 文档: 点击

Try this: 尝试这个:
//Use Handler().postDelayed //使用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;
  }

In my humble opinion you need to avoid calling 'new' every click. 以我的拙见,您需要避免每次点击都称为“新”。

To fix this you can use constant values to navigation drawer's android:layout_width and android:layout_height attributes ie. 为了解决这个问题,您可以使用常量值来导航抽屉的android:layout_widthandroid:layout_height属性,即。

        android:layout_width="@dimen/navigation_drawer_width"
        android:layout_height="match_parent"

You may also want to enable hardware acceleration on activity in AndroidManifest.xml 您可能还想对AndroidManifest.xml活动启用硬件加速

          <activity
              android:name=".ui.SomeActivity"
              android:hardwareAccelerated="true" />

The lag is caused by two heavy operations (fragment replacement and drawer animation) happening in the same thread (main thread aka UI thread). 滞后是由于在同一线程(主线程或UI线程)中发生两次繁重的操作(片段替换和抽屉动画)引起的。

One way to address this problem is to call the replacement of fragments after the drawer completely closes. 解决此问题的一种方法是在抽屉完全关闭后调用碎片更换。 In this way the two operations will not happen simultaneously. 这样,这两个操作将不会同时发生。

In addition, it's a nice design implementation to cross fade a progress bar with the fragment container. 另外,将片段容器与进度条交叉淡入淡出是一个不错的设计实现。

Inside your Activity you should have something like this: 在您的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
                }
            })

}

Inside your xml, you should have something like this: 在您的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>
....

Just close the Drawer in some delay, it makes close animation smooth只需延迟关闭抽屉,即可顺利关闭 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
        }

After call drawerLayout.closeDrawers() create a new Thread 调用抽屉布局.closeDrawers()之后,创建一个新线程

new Thread(new Runnable() {
public void run() {
try {
     TimeUnit.MILLISECONDS.sleep(300);
     //Here call you fragmentManager
    } catch (InterruptedException e) {
     e.printStackTrace();
                    }
   }
 }).start();

of course you can vary MILISECONDS as you want. 当然,您可以根据需要改变MILISECONDS。 Sorry my english 对不起我的英语

The lag is caused by two heavy operations (fragment replacement and drawer animation) happening in the same thread (main thread aka UI thread). 滞后是由于在同一线程(主线程或UI线程)中发生两次繁重的操作(片段替换和抽屉动画)引起的。

In my case navigation header background image size is large, so its works on high performance devices but lack on low performance devices. 在我的情况下,导航标题背景图片的尺寸很大,因此它可以在高性能设备上使用,但在低性能设备上却无法使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Android中打开或关闭片段时导航抽屉落后于Android - Navigation drawer lags in Android when opening or closing fragment in Android 导航抽屉无法打开 - android - Navigation drawer not opening 打开另一个活动后关闭导航抽屉 - Closing the navigation drawer after opening another activity 导航抽屉滞后于ImageView - Navigation Drawer lags with an ImageView 在Recycler视图上添加Image View时,Android Navigation Drawer Animation滞后/放慢 - Android Navigation Drawer Animation Lags/Slows down when an Image View is added over Recycler view 单击抽屉中的任何项目而不在android中关闭时,更改导航抽屉中的视图和内容 - Changing the view and content inside navigation drawer when clicking on any item of drawer without closing in android 导航抽屉在某些设备上打开/关闭时会挂起 - Navigation Drawer hangs while opening/closing on some devices 向(打开/关闭)导航抽屉的活动添加(打开/关闭)按钮 - Add (open/close) button to activity for (opening/closing) the navigation drawer 打开时如何自定义导航抽屉的动画 - how to customize the animations of the navigation drawer when opening 打开导航抽屉时我的应用程序崩溃 - My app crashes when opening navigation drawer
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM