繁体   English   中英

导航抽屉在打开和关闭时滞后 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_widthandroid: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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM