当前位置: 首页 > 知识库问答 >
问题:

在BottomNavigationView中切换标签时的延迟

刘浩思
2023-03-14

我有一个包含BottomNavigationView的活动,这个bottomnav帮助该活动显示三个片段。这些片段加载良好,我使用AsyncTask来完成每一个繁重的操作,而在UI线程中,我会显示一个ProgressBar,直到所有内容都加载<我的片段有一个奇怪的行为:第一次加载片段时,实际显示它需要一些时间,而不是用进度条立即显示<这件事只有第一次发生,而且只发生在这个片段中<片段代码仅包含以下内容:

@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        new LoadData(getView(), getContext()).execute();
    }

private class LoadData extends AsyncTask<Void, Void, Void> {

        private View v;
        private Context context;

        public LoadData(View v, Context context) {
            items = new ArrayList<>();
            this.v = v;
            this.context = context;
        }

        @Override
        protected Void doInBackground(Void... voids) {
            setItems(context); //Heavy operation
            adapter = new DashAdapter(items, context);
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //shows progressbar
            progress = v.findViewById(R.id.DFProgress);
            progress.setVisibility(View.VISIBLE);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            setPager();
            //sets viewPager and hides progressbar
            progress.setVisibility(View.GONE);
        }
    }

我如何才能使片段以正确的方式加载?

共有3个答案

方季同
2023-03-14

当我尝试@KasımÖzdemir的答案时,每次活动启动时,底部导航视图中的第一个项目都会产生最初的连锁反应。(因为我使用的是material bottom navigation view,它具有默认的连锁反应。而且当我第一次点击时UI不可见,但我认为这是因为我使用了与@KasımÖzdemir不同的方法来更改单击项目时的活动片段。

我不想从第一个项目开始我的活动,而是从导航视图中的中间项目开始,在下面的案例中是“FragmentTwo”。所以涟漪效应是无关紧要的。

所以,我只是附加了片段,而不是添加它,然后隐藏它,现在没有涟漪,下面是代码在Kotlin中的外观。。。

    val firstFragment: Fragment = FragmentOne()
    val middleFragment: Fragment = FragmentTwo()
    val thirdFragment: Fragment = FragmentThree()
    var fragment: Fragment? = null
    var bnv: BottomNavigationView? = null

    bnv = findViewById(R.id.bottom_navigation)
    bnv!!.selectedItemId = R.id.middle_page

  //fragments attached other than the fragment linked with middle item    
    supportFragmentManager.beginTransaction().attach(firstFragment).commit()
    supportFragmentManager.beginTransaction().attach(thirdFragment).commit()

    supportFragmentManager.beginTransaction().add(R.id.activity_main_container, middleFragment())
        .commit()
 bnv!!.setOnItemSelectedListener { item ->

            when (item.itemId) {    
                R.id.first_page -> fragment = firstFragment
                R.id.middle_page -> fragment = middleFragment
                R.id.third_page -> fragment = thirdFragment    
            }
    
            if (item.isChecked){
                false
            }

            else {
                supportFragmentManager.beginTransaction()
                    .setCustomAnimations(R.anim.fade_in, R.anim.fade_out).replace(
                        R.id.activity_main_container,
                        fragment!!
                    ).commit()
                true
            }
        }

因此,使用附加也可以很好地工作,而不是添加然后隐藏它。。。有关更多信息,请查看此答案

(如果您还没有,请尝试使用导航组件进行底部导航,如下图所示。在某些情况下,它更方便,因为它可以自行处理默认的Backback管理。)

西门嘉澍
2023-03-14

您可以使用jetpack导航进行简单的底部栏导航

带Jetpack导航的简单底部导航:

让我们首先在应用程序的build.gradle文件中添加以下行,在应用程序中包含Jetpack导航库:

def nav_version = "2.1.0"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

我们首先创建一个简单的底部导航流。为此,您需要首先在单个活动布局文件中添加NavHostFrament。将其添加到FrameLayout标记内的activity_main.xml文件中。

<fragment
  android:id="@+id/fragNavHost"
  android:name="androidx.navigation.fragment.NavHostFragment"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:defaultNavHost="true"
  app:navGraph="@navigation/bottom_nav_graph" />

您将看到一个错误,显示“无法解析符号@导航/bottom_nav_graph”

    <?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/bottom_nav_graph.xml"
    app:startDestination="@id/homeFragment2">

    <fragment
        android:id="@+id/homeFragment2"
        android:name="com.wajahatkarim3.bottomnavigationdemo.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" />

    <fragment
        android:id="@+id/searchFragment2"
        android:name="com.wajahatkarim3.bottomnavigationdemo.SearchFragment"
        android:label="fragment_search"
        tools:layout="@layout/fragment_search" />

    <fragment
        android:id="@+id/notificationsFragment2"
        android:name="com.wajahatkarim3.bottomnavigationdemo.NotificationsFragment"
        android:label="fragment_notifications"
        tools:layout="@layout/fragment_notifications" />

    <fragment
        android:id="@+id/profileFragment2"
        android:name="com.wajahatkarim3.bottomnavigationdemo.ProfileFragment"
        android:label="fragment_profile"
        tools:layout="@layout/fragment_profile" />
</navigation>

是时候在我们的活动类中添加一些代码了。打开MainActivity。kt文件,并在其中创建方法setupViews()。在活动的onCreate()中调用此函数。在setupVeiws()方法中添加这些行。

    fun setupViews()
{
    // Finding the Navigation Controller
    var navController = findNavController(R.id.fragNavHost)

    // Setting Navigation Controller with the BottomNavigationView
    bottomNavView.setupWithNavController(navController)

    // Setting Up ActionBar with Navigation Controller
    // Pass the IDs of top-level destinations in AppBarConfiguration
    var appBarConfiguration = AppBarConfiguration(
        topLevelDestinationIds = setOf (
            R.id.homeFragment,
            R.id.searchFragment,
            R.id.notificationsFragment,
            R.id.profileFragment
        )
    )
    setupActionBarWithNavController(navController, appBarConfiguration)
}
阮炯
2023-03-14

我也有同样的问题。我有两个选择。

  1. 调用LoadData或
  2. 时使用后置延迟
  3. 首先手动添加所有片段。您自己管理导航项。

这样地:

val firstFragment: Fragment = FirstFragment()
val secondFragment: Fragment = SecondFragment()
val thirdFragment: Fragment = ThirdFragment()

val navView: BottomNavigationView = findViewById(R.id.nav_view)

var active = firstFragment
fm.beginTransaction().add(R.id.nav_host_fragment, thirdFragment, "3").hide(thirdFragment).commit()
fm.beginTransaction().add(R.id.nav_host_fragment, secondFragment, "2").hide(secondFragment).commit()
fm.beginTransaction().add(R.id.nav_host_fragment, firstFragment, "1").commit()

navView.setOnNavigationItemReselectedListener {  }
navView.setOnNavigationItemSelectedListener { item ->
       when (item.itemId) {
           R.id.navigation_first -> {
               fm.beginTransaction().hide(active).show(firstFragment).commit()
               active = firstFragment

           }
           R.id.navigation_second -> {
               fm.beginTransaction().hide(active).show(secondFragment).commit()
               active = secondFragment
           }
           R.id.navigation_third -> {
               fm.beginTransaction().hide(active).show(thirdFragment).commit()
               active = thirdFragment
           }
       }
        true
   }

并删除nav\u host\u片段中的这些行:

app:defaultNavHost="true"
app:navGraph="@navigation/mobile_navigation"
 类似资料:
  • 我有一个带有的布局,属性设置为: 菜单有五项: 第三项标签过长(第二个单词没有省略,只是没有显示): 标签稍微短一点会导致正确的行为: 有没有办法处理更长的标签?最好的解决方案是省略号并显示“更长的文本…”当全文没有空间时。

  • Google发布了带有BottomNavigationView的新支持库v25 有什么方法可以去除物品标签吗?

  • 我正在使用: Chrome55.0.2 Selenium WebDRiver 3.0.1与ChromeDRiver C#4.6.1(VS2015社区版) 我正在编写打开Chrome的自动化代码,打开一个选项卡,并导航到一个主页面URL。这个主页有我解析生成二级页面URL的信息。我的问题是,我不能编写在二级页面加载后切换回主页选项卡的代码,也不能编写从不离开主页的代码。我将解释我所追求的两个选择:

  • 这是我第一次尝试开发android应用程序。 我有一个带有ConstraintLayout的MainActivity,它具有BottomNavigationView。每当选择第一个导航项时,我想显示一个类别列表(显示在片段中),然后每当选择此类别时,将显示与该特定类别相关的另一个列表(显示在另一个片段中)。 我读到(Android-fragment.replace()不替换内容-将其放在顶部)它指

  • 我正在使用Selenium和Java,我正在使用这段代码在Mozilla中的选项卡之间切换,但它打开了一个新窗口而不是新选项卡。如何解决这个问题,或者有没有另一种在选项卡之间切换的方法?

  • 问题内容: 我有一个标签栏应用程序,并且在我的第一个视图上有一个按钮,当我按下该按钮时,需要在标签栏中以编程方式切换到第二个标签页。 我似乎不太明白如何获取索引等以切换到它,我已经尝试过类似的东西。 没有成功。 问题答案: 多数民众赞成在非常简单的tabBarController被声明为可选类型 视图控制器层次结构中最接近的祖先,它是一个标签栏控制器。如果视图控制器或其祖先之一是标签栏控制器的子代