Проблема боковой и нижней навигации при переносе Kotlin MainActivity на Java - PullRequest
0 голосов
/ 25 июня 2019

Короче говоря, я новичок в среде Android и немного больше, чем могу понять, пытаясь выучить Android и Kotlin. Я создал свои контроллеры пользовательского интерфейса в Kotlin и использовал пример кода Google для выполнения навигации по фрагментам. После этого я обнаружил, что для меня гораздо эффективнее программировать весь свой бэкэнд на Java. Не желая иметь дело с двумя языками в одном приложении, я успешно перенес все свои контроллеры пользовательского интерфейса с Kotlin на Java. Тем не менее, я застрял в моем классе MainActivity. Ниже приведена версия Kotlin, два файла макета XML и моя попытка Java-версии MainActivity.

Путаница связана с двумя вызовами методов setupBottomNavMenu () и setupNavigation Menu () в onCreate ().

Класс BottomNavigationView, по-видимому, не имеет метода setupWithNavController (NavController navController), как в Kotlin. Самое близкое, что я могу найти, это setupWithNavController (BottomNavigationView bottomNavigationView, NavController navController). Если я выберу это и закомментирую вызов в setupNavigation Menu (), приложение будет работать в портретном режиме, но вылетает, когда я наклоняю свой телефон (альбомный режим).

Класс NavigationView также не предлагает метод, который принимает один параметр типа NavController, как в версии Kotlin. Я снова выбрал аналогичный метод setupWithNavController (NavigationView navigationView, NavController navController), но после запуска моего приложения происходит сбой.

Может кто-нибудь пролить свет на это для меня? В этот момент я вращаю свои колеса, пытаясь понять, что происходит.

Мой импорт Gradle для навигации:

def nav_version = "2.1.0-alpha03"
implementation "androidx.navigation:navigation-fragment:$nav_version" // For Kotlin use navigation-fragment-ktx
implementation "androidx.navigation:navigation-ui:$nav_version" // For Kotlin use navigation-ui-ktx

Макет XML-портрета и ландшафта

<LinearLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

<androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />

<fragment
        android:id="@+id/my_nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        app:defaultNavHost="true"
        app:navGraph="@navigation/mobile_navigation" />

<com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:menu="@menu/bottom_nav_menu" />

<androidx.drawerlayout.widget.DrawerLayout
    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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimary"
            android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />

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

</LinearLayout>

<com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/nav_drawer_menu" />

MainActivity.kt

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.widget.Toolbar
import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.navigation.NavigationView

class MainActivity : AppCompatActivity(){

private lateinit var appBarConfiguration : AppBarConfiguration

override fun onCreate(savedInstanceState: Bundle?)
{
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val toolbar = findViewById<Toolbar>(R.id.toolbar)
    setSupportActionBar(toolbar)

    val host: NavHostFragment = supportFragmentManager
        .findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return

    // Set up Action Bar
    val navController = host.navController

    //Create AppBarConfiguration with the correct top-level destinations
    val drawerLayout : DrawerLayout? = findViewById(R.id.drawer_layout)
    appBarConfiguration = AppBarConfiguration(
        setOf(R.id.home_dest),
        drawerLayout)

    //set up bottom navigation (in portrait mode)
    setupBottomNavMenu(navController)

    //set up side navigation menu (in landscape mode)
    setupNavigationMenu(navController)

    //configure action bar for popping back on the stack.
    setupActionBar(navController, appBarConfiguration)
}

private fun setupBottomNavMenu(navController: NavController)
{
    val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav_view)
    bottomNav?.setupWithNavController(navController)
}

private fun setupNavigationMenu(navController: NavController)
{
    // In split screen mode, you can drag this view out from the left
    // This does NOT modify the actionbar
    val sideNavView = findViewById<NavigationView>(R.id.nav_view)
    sideNavView?.setupWithNavController(navController)
}

private fun setupActionBar(navController: NavController, appBarConfig : AppBarConfiguration)
{
    // This allows NavigationUI to decide what label to show in the action bar
    // By using appBarConfig, it will also determine whether to
    // show the up arrow or drawer menu icon
    setupActionBarWithNavController(navController, appBarConfig)
}

override fun onSupportNavigateUp(): Boolean
{
    // Allows NavigationUI to support proper up navigation or the drawer layout
    // drawer menu, depending on the situation
    return findNavController(R.id.my_nav_host_fragment).navigateUp(appBarConfiguration)
}
}

MainActivity.java

import android.os.Bundle;
import androidx.appcompat.widget.Toolbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationView;
import static androidx.navigation.Navigation.findNavController;
import static androidx.navigation.ui.NavigationUI.setupWithNavController;


public class MainActivity extends AppCompatActivity{

private AppBarConfiguration appBarConfiguration;
private NavController navController;
private DrawerLayout drawerLayout;
private Toolbar toolbar;

public MainActivity()
{
    //do nothing
}

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    navController = Navigation.findNavController(this, R.id.my_nav_host_fragment);

    drawerLayout = findViewById(R.id.drawer_layout);

    appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph())
            .setDrawerLayout(drawerLayout)
            .build();

    //set up bottom navigation (in portrait mode)
    setupBottomNavMenu(navController);

    //set up side navigation menu (in landscape mode)
    setupNavigationMenu(navController);

    //configure action bar for popping back on the stack.
    setupActionBar(navController, appBarConfiguration);
}

private void setupBottomNavMenu(NavController navController)
{
    BottomNavigationView bottomNav = findViewById(R.id.bottom_nav_view);
    setupWithNavController(bottomNav, navController);
}

private void setupNavigationMenu(NavController navController)
{
    // In split screen mode, you can drag this view out from the left
    // This does NOT modify the actionbar

    NavigationView sideNavView = findViewById(R.id.nav_view);
    setupWithNavController(sideNavView, navController);
}

private void setupActionBar(NavController navController, AppBarConfiguration appBarConfig)
{
    // This allows NavigationUI to decide what label to show in the action bar
    // By using appBarConfig, it will also determine whether to
    // show the up arrow or drawer menu icon

    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfig);
}

@Override
public boolean onSupportNavigateUp()
{
    // Allows NavigationUI to support proper up navigation or the drawer layout
    // drawer menu, depending on the situation
    return findNavController(findViewById(R.id.my_nav_host_fragment)).navigateUp();
}
}

1 Ответ

1 голос
/ 25 июня 2019

Синтаксис ?. - это оператор elvis , который выполняет только следующее выражение, если объект не равен нулю.

Следовательно, такой вызов, как bottomNav?.setupWithNavController(navController), состоит из двух частей:оператор elvis и функция расширения Kotlin (статический метод, который выглядит так, как если бы он был методом другого класса).

Эквивалентный код Java должен был бы выполнять обе эти функции, чтобыэквивалент:

if (bottomNav != null) {
    NavigationUI.setupWithNavController(bottomNav, navController);
}

(Выбор того, использовать ли import static androidx.navigation.ui.NavigationUI.setupWithNavController; или просто использовать статический метод напрямую, больше зависит от стиля - оба работают)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...