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

如何不间断地显示我的导航栏内容?

张淳
2023-03-14

我从头开始构建了一个可定制的导航抽屉(没有利用Android Studio提供的默认抽屉)。在我的天气应用程序的导航栏菜单https://i.stack.imgur.com/SIjdx.jpg,中,每当我选择菜单上的一个选项(比如设置),它就会显示选项的内容,以及底部的导航视图和我的活动工具栏内容,其中包括导航汉堡图标、编辑文本和搜索按钮(托管我的3个片段的活动),这会破坏应用程序,使其看起来非常难看,即https://i.stack.imgur.com/gxj5n.jpg(从那个截图来看,如果实施良好,整个内容应该是空的)。其他栏菜单选项的情况也是如此。我想要的只是一个空白的工作空间,我希望该应用程序只显示导航栏的内容,没有其余的。例子;https://i.stack.imgur.com/3Jtga.png,请告诉我该怎么做?

导航菜单的视图由以下代码控制(第185行):

@Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.settings_id:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
                        new Settings()).commit();
                break;
            case R.id.ads_upgrade_id:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
                        new Upgrade()).commit();
                break;
            case R.id.privacy_policy_id:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
                        new Privacy_Policy()).commit();
                break;
        }
        drawer.closeDrawer(GravityCompat.START);

        return true;
    }

“fragment”表示我当前正在使用我的活动上的fragment的容器视图来显示导航菜单内容,我知道这些内容肯定是错误的,那么我应该在replace中使用什么呢?我缺乏丰富的经验,因为这是我第一次开发应用程序,我花了3个小时孜孜不倦地独自尝试解决这个问题,结果证明失败了。

这是我的活动代码:

public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
    private DrawerLayout drawer;
    // Last update time, click sound, search button, search panel.
    TextView timeField;
    MediaPlayer player;
    ImageView Search;
    EditText textfield;
    // For scheduling background image change(using constraint layout, start counting from dubai, down to statue of liberty.
    ConstraintLayout constraintLayout;
    public static int count = 0;
    int[] drawable = new int[]{R.drawable.dubai, R.drawable.norway, R.drawable.eiffel_tower, R.drawable.hong_kong, R.drawable.statue_of_liberty,
            R.drawable.beijing, R.drawable.chicago, R.drawable.colombia, R.drawable.vienna,R.drawable.tokyo};
    Timer _t;

    private WeatherDataViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        // use home activity layout.

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        // Allow activity to make use of the toolbar

        drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);

        // Trigger action to open & close navigation drawer
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar
                , R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        timeField = findViewById(R.id.textView9);
        Search = findViewById(R.id.imageView4);
        textfield = findViewById(R.id.textfield);
        //  find the id's of specific variables.

        BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
        // host 3 fragments along with bottom navigation.
        final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
        assert navHostFragment != null;
        final NavController navController = navHostFragment.getNavController();
        NavigationUI.setupWithNavController(bottomNavigationView, navController);

        // Make hourly & daily tab unusable
        bottomNavigationView.setOnNavigationItemSelectedListener(item -> {

            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportFragmentManager().popBackStack();
            }
            return false;
        });

        navController.addOnDestinationChangedListener((controller, destination, arguments) -> navController.popBackStack(destination.getId(), false));

        // For scheduling background image change
        constraintLayout = findViewById(R.id.layout);
        constraintLayout.setBackgroundResource(R.drawable.dubai);
        _t = new Timer();
        _t.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                // run on ui thread
                runOnUiThread(() -> {
                    if (count < drawable.length) {

                        constraintLayout.setBackgroundResource(drawable[count]);
                        count = (count + 1) % drawable.length;
                    }
                });
            }
        }, 5000, 5000);

        Search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // make click sound when search button is clicked.
                player = MediaPlayer.create(HomeActivity.this, R.raw.click);
                player.start();

                getWeatherData(textfield.getText().toString().trim());
                // make use of some fragment's data

                Fragment currentFragment = navHostFragment.getChildFragmentManager().getFragments().get(0);
                if (currentFragment instanceof FirstFragment) {
                    FirstFragment firstFragment = (FirstFragment) currentFragment;
                    firstFragment.getWeatherData(textfield.getText().toString().trim());
                } else if (currentFragment instanceof SecondFragment) {
                    SecondFragment secondFragment = (SecondFragment) currentFragment;
                    secondFragment.getWeatherData(textfield.getText().toString().trim());
                } else if (currentFragment instanceof ThirdFragment) {
                    ThirdFragment thirdFragment = (ThirdFragment) currentFragment;
                    thirdFragment.getWeatherData(textfield.getText().toString().trim());
                }
            }

            private void getWeatherData(String name) {

                ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);

                Call<Example> call = apiInterface.getWeatherData(name);

                call.enqueue(new Callback<Example>() {
                    @Override
                    public void onResponse(@NonNull Call<Example> call, @NonNull Response<Example> response) {

                        try {
                            assert response.body() != null;
                            timeField.setVisibility(View.VISIBLE);
                            timeField.setText("First Updated:" + " " + response.body().getDt());
                        } catch (Exception e) {
                            timeField.setVisibility(View.GONE);
                            timeField.setText("First Updated: Unknown");
                            Log.e("TAG", "No City found");
                            Toast.makeText(HomeActivity.this, "No City found", Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
                        t.printStackTrace();
                    }

                });
            }

        });
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.settings_id:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
                        new Settings()).commit();
                break;
            case R.id.ads_upgrade_id:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
                        new Upgrade()).commit();
                break;
            case R.id.privacy_policy_id:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
                        new Privacy_Policy()).commit();
                break;
        }
        drawer.closeDrawer(GravityCompat.START);

        return true;
    }

    @Override
    public void onBackPressed() {
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
            // Open/close drawer animation
        }
    }
}

如果您需要任何其他代码来调查问题,请告诉我。我只是试图避免发布太多

编辑:

我的旧底部导航图:

<?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/my_nav"
    app:startDestination="@id/firstFragment">

    <fragment
        android:id="@+id/firstFragment"
        android:name="com.viz.lightweatherforecast.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" />
    <fragment
        android:id="@+id/secondFragment"
        android:name="com.viz.lightpreciseweatherforecast.SecondFragment"
        android:label="fragment_second"
        tools:layout="@layout/fragment_second" />
    <fragment
        android:id="@+id/thirdFragment"
        android:name="com.viz.lightpreciseweatherforecast.ThirdFragment"
        android:label="fragment_third"
        tools:layout="@layout/fragment_third" />
</navigation>

我的新导航栏图:

<?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/bar_nav"
    app:startDestination="@id/firstFragment">

    <fragment
        android:id="@+id/firstFragment"
        android:name="com.viz.lightweatherforecast.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" />
    <fragment
        android:id="@+id/settings_id"
        android:name="com.viz.lightweatherforecast.Settings"
        android:label="@string/settings"
        tools:layout="@layout/settings" />
    <fragment
        android:id="@+id/ads_upgrade_id"
        android:name="com.viz.lightweatherforecast.Upgrade"
        android:label="@string/upgrade_to_remove_ads"
        tools:layout="@layout/upgrade" />
    <fragment
        android:id="@+id/privacy_policy_id"
        android:name="com.viz.lightweatherforecast.Privacy_Policy"
        android:label="@string/privacy_policy"
        tools:layout="@layout/privacy_policy"/>

</navigation>

共有2个答案

酆晔
2023-03-14

我想我很好地理解了你的问题(如果我没有错的话)。问题是你现在得到的行为是正常的情况。您正在使用相同的主机活动来托管导航抽屉底部导航片段,因此当您尝试从同一主机导航到另一个片段时,主机的直接子视图BottomNavBar正在显示。我认为您可以通过几种不同但非常简单的逻辑方式解决这个问题。

  1. (不推荐)对<code>设置</code>页面使用不同的活动。就像<code>startActivity(这,
冯哲彦
2023-03-14

您正在使用导航体系结构组件,因此 navController 是应该控制片段事务的组件,您正在使用 BottomNavigationView 执行此操作。

但是在navDrawer中,您正在通过支持FragmentManager进行交易,这应该通过navController来完成,因为两者都以不同的方式处理导航。

每当我在菜单上选择一个选项时(比如设置),它会在底部的导航视图中显示选项的内容

这是因为BottomNavView是活动的一部分,您需要将其移动到片段中;这需要更改应用程序的导航设计;要做到这一点,请更改应用程序导航,如下所示:

主导航:

<navigation
 ..... >

    <fragment
        android:name="......HomeFragment"/>

    <fragment
        android:name="......SettingFragment"/>

    <fragment
        android:name="......AdsUpgradeFragment"/>
        
    <fragment
        android:name="......PrivacyPolicyFragment"/>        
        
        
</navigation>

< code>HomeFragment是应该保存< code > BottomNaviagtionView 而不是activity的片段;当您导航到SettingFragment时,navConroller将替换navHostFragment中的整个片段,因此< code > BottomNaviagtionView 不会显示。

我的活动的工具栏内容,包括导航汉堡包图标,编辑文本和搜索按钮(托管我的3个片段的活动),这会破坏应用程序并使其看起来非常丑陋

底部导航视图不同,您不能使用用作supportActionBar的工具栏,因为要更改其外观,需要多次设置supportActionBar;将复制它;因此,您必须接受单个工具栏;但是,您可以隐藏/显示包含搜索按钮的布局

navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
    LinearLayout searchBar = findViewById(R.id.searchbar); // change searchbar according to the layout id that holds the search button and the EditText
    if (destination.getId() == R.id.nav_home) {
        searchBar.setVisibility(View.VISIBLE);

    } else {
        searchBar.setVisibility(View.GONE);
    }

});

是的,当点击返回时,他们会退出应用程序

要随时退出应用程序,请在任何片段中按下底部后退按钮,请使用onBackPressedDispatcher()在这些片段中(在您的情况下设置碎片,PrivacyPolicyFragment,

并确保< code>appBarConfiguration不引用这些片段,以便显示向上按钮而不是汉堡。

requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) {
        @Override
        public void handleOnBackPressed() {
            // Exit the app when back is pressed
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                requireActivity().finishAndRemoveTask();
            else requireActivity().finish();
        }
    });

另外,请确保您设置的抽屉布局

NavigationView navView = findViewById(....);

appBarConfiguration = new AppBarConfiguration.Builder(
        R.id.nav_home) // remove up button from all these fragments >> Keep the up/back button in R.id.settings_id, R.id.settings_id, ads_upgrade_id, privacy_policy_id
        .setOpenableLayout(drawer)
        .build();

NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);

并且要使主页片段默认隐藏在 navDrawer 中:

navView.getMenu().findItem(R.id.nav_home).setVisible(false); // adjust R.id.nav_home to yours

我目前只有一个导航图。firstFraank代表今天、第二小时和第三天,我正在使用的是其他天气选项卡,但您建议的是导航栏菜单,我应该用我的替换您的还是为您的建议创建一个新选项卡?

您应该使用两个navGraph,第一个是我建议的主导航;第二个是您已经使用的BottomNavigationView导航;这是因为我们将BottomNavigationView从活动布局转移到main/home片段布局;它'建议BottomNavigationView应该有一个单独的navGraph;

因此,您现在需要两个< code > FragmentContainerView ;第一个在活动布局中,它引用了本答案中提供的导航图,第二个在home片段布局中,它引用了< code > BottomNavigationView 的原始导航图。

样本:

 类似资料:
  • 出于某种原因,我使用引导主题的导航栏没有显示为块。我正在使用我的index.html页面的轮播模板,并希望在我的其余页面上使用相同的主题,只是没有轮播。然而,当我拿出旋转木马时,我的第二个div坐在我的导航栏下。 下面是我导航栏的代码: 还有一个指向我的小提琴的链接,我的CSS位于引导CSS之上: https://jsfiddle.net/czz2Lm1n/

  • 在angular中,我试图确保我所在的页面在navbar上被高亮显示--我想这可能是我正在使用的自举nav的原生版本,但它似乎不起作用。 导航 有没有一个css脚本或我可以使用的东西来实现这一点?

  • 如何在Jellybean模拟器上启用系统导航栏(包括HOME/BACK/MENU)? 在谷歌上搜索这个,有人说可以通过更改属性来完成,但是我找不到在哪里设置这个常数。有人能帮我吗?

  • ap.showOptionButton() 显示导航栏右侧按钮。 代码示例 <script src="https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.inc.min.js"></script> <button class="btn btn-default">显示 optionButton</button

  • ap.showNavigationBarLoading() 显示导航栏加载图标。 代码示例 <script src="https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.inc.min.js"></script> <button class="btn btn-default">showNavigationB

  • 我一直在Stack上寻找一些关于这个的指导,但是没有一个问题被问到这么深,答案也没有更新到最新的Swift版本,甚至没有更新到最新的Swift版本。 这是我所拥有的: 带有两个栏项目的导航控制器: 我的目标是:使导航根视图控制器的导航栏透明(但按钮和标题仍然可见),而不是子导航——没有奇怪的细微差别,比如之前的彩色闪光,或切断导航栏(参见gif) 我尝试过的事情: 在<代码>视图将出现(u动画:B