I am using BottomNavigationViewEx (BottomNavigationView with really good features). I have layout and now I want to 'connect' this navigation with my Activities. Usually it's connect with Fragments but my all activities extends AppCompatActivity.
Here's my nav.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.activity.RecipesActivity">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/navigation_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
<com.ittianyu.bottomnavigationviewex.BottomNavigationViewEx
android:id="#+id/navigation_view"
android:layout_width="0dp"
android:layout_height="65dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:background="#color/colorPrimary"
app:itemIconTint="#color/draw_item"
app:itemTextColor="#color/draw_item"
app:menu="#menu/nav_items" />
</android.support.constraint.ConstraintLayout>
How can I make this navigation visible on all activities and setup Click Listeners on items? I have five items on my navigation and I want to show for example activity 1 when I click on item 1 and so on.
I would recommend using Fragments for switching between tabs. Few pros when using Fragments:
It will prevent from destroying and creation of the activities and screen blinking.
It is easier to hold only one BottomNavigationView.
Single Responsibility for handling navigation, saving and restoring states.
Related
I have a MainActivity that installSplashScreen() at first, then it will load the WebView, the webviewFragment is in other file, I am trying to use splashScreen.setKeepOnScreenCondition{ } to keep splash screen showing until the webviewFragment reach to onPageFinished() state, how am I supposed to do that?
There are several alternatives to communicate both components:
you may use a listener in your fragment that notifies the activity,
you may cast the activity from fragment context to notify it,
you may use the activity ViewModel and observer pattern to notify the change
singletons though not recommended
event bus implementations
send a broadcast and receive it with a BroadCastListener in your splash or MainActivity.
You can use a layout like this
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="#+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/cl_container_splash"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
Frame Layout (Parent)
WebView (visibility = gone)
Splash Screen (visible)
Now load your url, and in your onPageFinished() call following.
binding.webView.visibility = View.Visible
binding.root.removeView(binding.clContainerSplash)
I have a navigation controller fragment defined inside my activity_main that has a match height and width of parent. So when I navigate between fragments, it replaces the entire screen. Now say I navigate to a fragment that loads up a material card. I want that material card to have its own navigation controller that takes up the height and width of the material card. So when I use its navigation controller, it will only replace fragments within the material card view and not change the parent's view.
Is there a way to have two navigation host fragments? So I can define one inside activity_main and then another one that I can define inside the child fragment.
activity_main:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/barrier"
app:navGraph="#navigation/base_nav_graph" />
childfragment:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_layout"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="600dp"
android:layout_height="match_parent"
android:layout_gravity="end"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<fragment
android:id="#+id/nav_child_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:navGraph="#navigation/child_nav_graph" />
See advanced sample
https://github.com/android/architecture-components-samples/tree/master/NavigationAdvancedSample
There used multiple navigation controllers for BottomNavigationView items
I am having a weird issue which might be very simple to solve but I don't know why its behaving like it does. I have two screens A and B. Navigation is from A -> B. On B, I have parent view as LinearLayout (LL) as
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/container"
android:orientation="vertical"
android:background="#color/tcRaspberry"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:animateLayoutChanges="true"
android:layout_height="match_parent">
<include
app:layout_constraintBottom_toTopOf="#+id/bottomSheetContainer"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:id="#+id/toolbarx"
layout="#layout/include_toolbarx"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_marginStart="#dimen/itinerary_start_margin"
android:layout_marginEnd="#dimen/itinerary_start_margin"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:contentDescription="#null"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="#dimen/itinerary_start_margin"
app:layout_constraintStart_toStartOf="parent"
android:id="#+id/myAccountImage"
android:layout_gravity="center"
app:srcCompat="#drawable/ic_panorama_circle_24dp"
android:layout_width="#dimen/image_size_profile"
android:layout_height="#dimen/image_size_profile"/>
<androidx.appcompat.widget.AppCompatTextView
android:textSize="20sp"
android:contentDescription="#string/travel_counsellor_contact"
android:layout_marginStart="#dimen/top_margin"
app:layout_constraintTop_toTopOf="#+id/myAccountImage"
app:layout_constraintStart_toEndOf="#+id/myAccountImage"
app:layout_constraintBottom_toBottomOf="#+id/myAccountImage"
android:id="#+id/myAccountTitle"
android:textAppearance="#style/TcTextAppearance.Bold.Header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/my_account"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
Even though the parent LL's height (id: container) is set as match_parent and is filling whole screen, its still accepting click events from previous screen A. The only way I got it to not accept clicks from A is to put a ClickListener on it which seems like a hack to me. What can I do to prevent it taking clicks from A.
Make the view that should block the call clickable via xml android:clickable="true" or set a click handler for it from fragment/activity
I'm using the "new" Android Jetpack navigation, instead of relying on FragmentManager. I've got a simple main layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MainActivity">
<FrameLayout
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/bottomNav">
<fragment
android:id="#+id/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/navigation_app" />
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="#menu/bottom_menu"
app:layout_constraintBottom_toBottomOf="#+id/root"/>
</android.support.constraint.ConstraintLayout>
And two additional layouts: "Splashscreen" with a TextView, "Login" with a button. The splashscreen fragment is used as starting point, and has a listener defined as follows:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
textView.setOnClickListener{
findNavController(nav_host_fragment).navigate(R.id.action_splashScreenFragment_to_loginFragment)
}
}
screenshot
Instead of replacing TextView fragment with Button fragment, the Button fragment is stacked on top.
I've only encountered workarounds such as setting a background color, and clickable parameter, which I consider to be more of a hack, as I believe that the behaviour is exactly the same, but the fragment below is simply hidden. How to properly switch fragments using the NavController?
Issue seems to have occured because of these two lines:
val host = NavHostFragment.create(R.navigation.navigation_register_login)
supportFragmentManager.beginTransaction().replace(R.id.nav_host_fragment,host).setPrimaryNavigationFragment(host).commit()
I guess they shouldn't be called, and all basic requirements are fulfilled by this line in layout:
android:name="androidx.navigation.fragment.NavHostFragment"
You need to use popUpTo and popUpToInclusive to clear the backstack.
Check the Android Developers docs
I am working on a project where I have an activity, which has two fragments loaded in.
I have this working except I want to put a touch bar in the middle between the two fragments, that will allow the user to drag the bar which would then resize the each fragment, i.e. make one fragment grow the other fragment shrink.
Below is the current layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools">
<fragment android:name="com.company.myapp.LoginFragment"
android:id="#+id/login_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<fragment android:name="com.company.myapp.ApiFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/api_fragment" />
</LinearLayout>
Is there a specific way to do this in Android via an API or will I need to add my own and use touch/drag listeners to resize appropriately.