I was trying to implement Android NavigationDrawer menu with Base Activity to show navigation drawer for nested activities using Kotlin.
According to tutorial activity_base_drawer.xml contains content_layout, which contains FrameLayout and in this FrameLayout my activity should be rendered.
NavigationDrawer menu itself working fine but it doesn't render activity_main.xml to FrameLayout, so it is always shows content_layout.xml i.e. empty screen.
What I have missed? How could I render activity_main to FrameLayout?
activity_base_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.BaseDrawerActivity"
tools:openDrawer="start"
android:fitsSystemWindows="true">
<include layout="#layout/content_layout"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
<com.google.android.material.navigation.NavigationView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_gravity="start"
android:id="#+id/nav_view"
app:headerLayout="#layout/main_drawer_header"
app:menu="#menu/main_drawer_menu"/>
</androidx.drawerlayout.widget.DrawerLayout>
content_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/appBarLayout"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/app_main"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:titleTextColor="#color/app_main_text"/>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/activityContainer"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="#+id/appBarLayout">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
BaseDrawerActivity.kt
open class BaseDrawerActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
lateinit var drawerLayout: DrawerLayout
override fun setContentView(view: View?) {
drawerLayout= layoutInflater.inflate(R.layout.activity_base_drawer, null) as DrawerLayout
val container = drawerLayout.findViewById<FrameLayout>(R.id.activityContainer)
container.addView(view)
super.setContentView(drawerLayout)
val toolbar: Toolbar =drawerLayout.findViewById(R.id.toolBar)
setSupportActionBar(toolbar)
val navigationView:NavigationView=drawerLayout.findViewById(R.id.nav_view)
navigationView.setNavigationItemSelectedListener(this)
val togle=ActionBarDrawerToggle(this#BaseDrawerActivity, drawerLayout, toolbar, R.string.menu_drawer_open, R.string.menu_drawer_close)
drawerLayout.addDrawerListener(togle)
togle.syncState()
}
}
MainActivity.kt
class MainActivity : BaseDrawerActivity() {
var activityMainBinding: ActivityMainBinding? =null
override fun onCreate(savedInstanceState: Bundle?) {
activityMainBinding=ActivityMainBinding.inflate(layoutInflater)
setContentView(activityMainBinding!!.root)
super.onCreate(savedInstanceState)
}
}
Related
I am learning Kotlin, have done apps in Java before. I now have an activity with an Toolbar, NavigationView and a FragmentView. As I understand this: Fragment Tutorial, it is enough to state the Fragment in the xml file.
I have this activity_main.xml file:
<?xml version="1.0" encoding="utf-8"?>
<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/navigation_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/main_app_bar_layout"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="#style/AppTheme.AppBarOverlay"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/main_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#android:color/holo_blue_light"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/main_navigation"
android:layout_marginTop="?attr/actionBarSize"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/navigation_header"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/main_app_bar_layout"
app:menu="#menu/navigation_menu" />
<androidx.fragment.app.FragmentContainerView
android:layout_marginTop="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_container"
android:name="com.example.android.camerax.tflite.TestFragment"
tools:layout="#layout/fragment_test" />
</androidx.drawerlayout.widget.DrawerLayout>
This is the fragment_test.xml:
<androidx.constraintlayout.widget.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.camerax.tflite.TestFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment"
android:textAlignment="center"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This is the Activity:
class CameraActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
private lateinit var fragment: CameraActivityFragment
private lateinit var navigationDrawer: DrawerLayout
private lateinit var toolbar: Toolbar
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera)
navigationDrawer = findViewById(R.id.navigation_container)
// Handle user consent update
toolbar = findViewById(R.id.main_toolbar)
setSupportActionBar(toolbar)
val toggle = ActionBarDrawerToggle(
this,
navigationDrawer,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
)
navigationDrawer.addDrawerListener(toggle)
toggle.syncState()
val navigationView: NavigationView = findViewById(R.id.main_navigation)
navigationView.setNavigationItemSelectedListener(this)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.show_recordings) {
// Start ListView
}
navigationDrawer.closeDrawer(GravityCompat.START)
return true
}
}
and here is the TestFragment.kt:
class TestFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_test, container, false)
}
companion object {
// TODO: Rename and change types and number of parameters
#JvmStatic
fun newInstance(param1: String, param2: String) =
TestFragment().apply {
arguments = Bundle().apply {
}
}
}
}
I have tried to read the link above and also follow this: AndroidTrivia. No success and I really think this is quite basic and should work. When I run the debugger I can see that onCreateView is called in the Fragment, as it should be.
This is how it looks. Sometimes, the text blips on the screen. So seems like something is overwriting the fragment?
screenshot 1
screenshot 2
Edit
After updating the FragmentContainerView with elevation 9dp, the text is shown. But now the Toolbar is hidden, although there is a marginTop for the FragmentContainerView. Screenshot 3
There are two things I would like to suggest here.
First if possible get back to ConstraintLayout as in your last answer. It is not necessary for sure, but would recommend.
Second the blipping might be cause by the difference in elevation since the elevation of NavigationView is different.
So I suggest you add the following to your FragmentContainerView
<androidx.fragment.app.FragmentContainerView
android:layout_marginTop="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_container"
android:elevation="9dp"
android:name="com.example.android.camerax.tflite.TestFragment"
tools:layout="#layout/fragment_test" />
9dp since most Android Views like BottomNav etc are upto 8dp
Also would recommend to modify your fragment_test as follows and add the following
<androidx.constraintlayout.widget.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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:clickable="true"
android:focusable="true"
tools:context="com.example.android.camerax.tflite.TestFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment"
android:textAlignment="center"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I am trying to Implement Navigation drawer but when I run my application and click on items in the drawer it just closes the drawer without doing showing the toast. nothing is happening with my drawer when I click an Item to navigate i.e The content inside Navigation Drawer is not clickable i.e the menu.
Below are my codes for Navigation drawer:
Activity Main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/content_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<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"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header"
app:menu="#menu/nav_menu"/>
<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"
tools:context=".FirstMain"
android:orientation="vertical"
android:gravity="center">
<TextView
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
android:background="#color/back"
android:fontFamily="#font/berkshire_swash"
android:gravity="center"
android:text="#string/app_name"
android:textAlignment="center"
android:textColor="#color/txt"
android:textSize="50sp"
android:textStyle="bold" />
<Button
android:id="#+id/button"
android:layout_width="165dp"
android:layout_height="wrap_content"
android:layout_margin="30sp"
android:background="#color/back"
android:fontFamily="#font/berkshire_swash"
android:gravity="center_horizontal"
android:padding="10sp"
android:text="PLAY"
android:textColor="#color/txt"
android:textSize="35sp"
android:textStyle="bold" />
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
nav_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_rule"
android:icon="#drawable/rules"
android:title="Rules" />
<item
android:id="#+id/nav_about"
android:icon="#drawable/about"
android:title="About"/>
</group>
</menu>
Content_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light">
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/puzzle">
</LinearLayout>
</LinearLayout>
Main.kt
class FirstMain : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener{
lateinit var btn : Button
lateinit var toolbar: Toolbar
lateinit var drawerLayout: DrawerLayout
lateinit var navView: NavigationView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_first_main)
btn = findViewById(R.id.button)
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
drawerLayout = findViewById(R.id.drawer_layout)
navView = findViewById(R.id.nav_view)
val toggle = ActionBarDrawerToggle(
this, drawerLayout, toolbar, 0, 0
)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
btn.setOnClickListener {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
navView.setNavigationItemSelectedListener(this)
}
override fun onNavigationItemSelected(p0: MenuItem): Boolean {
p0.isChecked = true
when (p0.itemId) {
R.id.nav_rule -> {
Toast.makeText(this, "Profile clicked", Toast.LENGTH_LONG).show()
}
R.id.nav_about -> {
Toast.makeText(this, "Messages clicked", Toast.LENGTH_LONG).show()
}
}
drawerLayout.closeDrawer(GravityCompat.START)
return true
}
}
Your code looks all good, weird it doesn't work but you can try and add
navView.bringToFront();
navView.setNavigationItemSelectedListener(this)
When I added DrawerToggle(Hamburger) by using kotlin, the ImageView (TravelPocket) moved to right.
So, it is not in center..
I want to make it move to center not using margin or padding property.
below is my image.
problem image
activity_main.xml
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/drawer"
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"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="48dp">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentTop="true"
android:background="#color/colorPrimary"
app:contentInsetStart="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="14dp"
android:src="#drawable/ic_logo"/>
</RelativeLayout>
</androidx.appcompat.widget.Toolbar>
</RelativeLayout>
MainActivity.class
class MainActivity : AppCompatActivity() {
lateinit var drawerToggle: ActionBarDrawerToggle
var currentTime: Long = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
drawerToggle = ActionBarDrawerToggle(this, drawer, toolbar,0,0)
drawer.addDrawerListener(drawerToggle)
drawerToggle.syncState()
}
}
To bind my StaffViewModel data to StaffActivity view that has DrawerLayout and NavigationView. In that NavigationView there was a layout nav_header_staf that consist of staff name and email. How can i bind my viewmodel to that nav_header_staff to replace staff name and email
I have tried to bind the view model in both layout in activity_staff and nav_header_staff layout, but databinding doesn't work.
Here is what i have tried in my StaffActivity.kt
class StaffActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, AnkoLogger {
private var fragmentManager: FragmentManager = supportFragmentManager
private lateinit var drawerLayout: DrawerLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//Create View Model
val staffBundle = intent.getBundleExtra(StaffModel.NAME)
val staff = staffBundle.getSerializable(StaffModel.NAME) as StaffModel
//Create databinding
val staffViewModel = StaffViewModel(staff)
val binding = DataBindingUtil.setContentView<ViewDataBinding>(this, R.layout.activity_staff)
binding!!.setVariable(BR.staff, staffViewModel)
val toolbar: Toolbar = toolbar
setSupportActionBar(toolbar)
val fab: FloatingActionButton = fab
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
drawerLayout = drawer_layout
val navView: NavigationView = nav_view
val toggle = ActionBarDrawerToggle(
this, drawerLayout, toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
navView.setNavigationItemSelectedListener(this)
}
and here is the activity_staff.xml layout
<layout>
<data xmlns:android="http://schemas.android.com/apk/res/android">
<variable name="staff" type="id.code.sakilarentaldvd.viewModel.StaffViewModel"/>
</data>
<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"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_staff"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<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"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_staff"
app:menu="#menu/activity_staff_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
and here is the nav_header_staff.xml layout
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data xmlns:android="http://schemas.android.com/apk/res/android">
<variable name="staff" type="id.code.sakilarentaldvd.viewModel.StaffViewModel"/>
</data>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:id="#+id/staffHeader"
android:layout_height="#dimen/nav_header_height"
xmlns:tools="http://schemas.android.com/tools"
android:background="#drawable/side_nav_bar"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:theme="#style/ThemeOverlay.AppCompat.Dark"
android:orientation="vertical"
android:gravity="bottom">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="#dimen/nav_header_vertical_spacing"
app:srcCompat="#mipmap/ic_launcher_round"
android:contentDescription="#string/nav_header_desc"
android:id="#+id/imageView"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/nav_header_vertical_spacing"
tools:text="username"
android:text="#{staff.staffName}"
android:textAppearance="#style/TextAppearance.AppCompat.Body1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="blabla#sakila.org"
android:text="#{staff.email}"
android:id="#+id/textView"/>
</LinearLayout>
</layout>
here is what the result does
Thank You stackoverflow, i know what i missed, here is my solution
what i change in StaffActivity.kt
class StaffActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, AnkoLogger {
private var fragmentManager: FragmentManager = supportFragmentManager
private lateinit var drawerLayout: DrawerLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//Create View Model
val staffBundle = intent.getBundleExtra(StaffModel.NAME)
val staff = staffBundle.getSerializable(StaffModel.NAME) as StaffModel
//Create databinding
val staffViewModel = StaffViewModel(staff)
//remove binding because no need to link view model with this layout
setContentView(R.layout.activity_staff) // setActivityLayout
...
// I override this object method
val toggle =object: ActionBarDrawerToggle(
this, drawerLayout, toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
){// do binding in this method
override fun onDrawerStateChanged(newState: Int) {
val binding2 = DataBindingUtil.bind<NavHeaderStaffBinding>(findViewById(R.id.staffHeader))
binding2!!.staff= staffViewModel
super.onDrawerStateChanged(newState)
}
}
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
navView.setNavigationItemSelectedListener(this)
}
I made few changes in activity_staff.xml layout, by removing <layout> and <data> tags
<?xml version="1.0" encoding="utf-8"?>
<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"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_staff"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<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"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_staff"
app:menu="#menu/activity_staff_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>
so this is the result
result
I'm trying to set an onclicklistener in my fragment which has a custom toolbar included and in the toolbar I have a bell icon which I am trying to put onclicklistener on but isn't working
This is the toolbar custom_toolbar.xml
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:title="#string/app_name">
<RelativeLayout
android:id="#+id/notification_bell"
..>
<ImageView
..>
<ImageView
..>
<TextView
..>
</RelativeLayout>
</androidx.appcompat.widget.Toolbar>
This is the fragment.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".landing.ui.fragment.HomeFragment">
<include android:id="#+id/custom_toolbar"
layout="#layout/custom_toolbar"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Then in Fragment.kt
class HomeFragment : Fragment() {
private fun initbell(notificationCount:Int) {
custom_toolbar.notification_bell.setOnClickListener {
Log.e("Fragment","bell clicked")
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
init()
.........
}
private fun init() {
initComponent()
..........
}
private fun initComponent() {
initbell(it)
..........
}
}
}
When the bell is clicked I want to perform some action. Currently, I should be able to display the log.
And also Im able to access it and change its visibility so its not a problem of initiating
Try this,
Add an id to toolbar
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
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="?attr/actionBarSize"
android:id="#+id/tb_toolbar"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:title="#string/app_name">
<RelativeLayout
android:id="#+id/notification_bell"
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#color/colorAccent" />
Then inside fragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
(context as AppCompatActivity).setSupportActionBar(tb_toolbar)
notification_bell.setOnClickListener {
Toast.makeText(context, "Yeaey", Toast.LENGTH_LONG).show()
}
}
Add an id to Toolbar tag in xml and then in kotlin file add bellow line in
onViewCreated method
(context as AppCompatActivity).setSupportActionBar(your_toolbar_id)
your_toolbar_id.notification_bell.setOnClickListener {
Log.d("TAG", "Your Log message here")
}
If what you want is to make the RelativeLayout handle the click, you should add the android:clickable attribute to it:
<RelativeLayout
android:id="#+id/notification_bell"
android:clickable="true"
..>
That's because a RelativeLayout will let the touch event passed from it so the child view can handle the event.
Alternate :-
Take Relative layout as the header in fragment class like this
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".landing.ui.fragment.HomeFragment">
<RelativeLayout
android:id="#+id/header_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<ImageView
..>
<ImageView
..>
<TextView
..>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
and in fragment class with onCreate()
header_bar.setOnClickListener {
Log.e("Fragment","bell clicked")
}
So I was looking into it and found that there was a small mistake that is I had to use AppBar Layout which actually solved the problem as the fragment.xml was not able to get the appbar layout so it wasn't recognizing the clicks. After this it worked like a charm
In fragment.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".landing.ui.fragment.HomeFragment">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="#+id/custom_toolbar"
layout="#layout/custom_toolbar"/>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>