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>
Related
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)
}
}
I'm trying to use view binding to change the visibility of an ImageView in the app bar when I navigate to a certain fragment. The structure of the app is pretty much like the stock Navigation Drawer Activity in Android Studio.
Since the app_bar_main.xml layout is included in activity_main.xml and has an id, I figured I should be able to just inflate the ActivityMainBinding and reference the app bar and its views. So I do like in the documentation to access the binding from the fragment:
private var _binding: FragmentChooseVehicleBinding? = null
private var _mainBinding: ActivityMainBinding? = null
private val binding get() = _binding!!
private val mainBinding get() = _mainBinding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
chooseVehicleViewModel =
ViewModelProvider(this).get(ChooseVehicleViewModel::class.java)
_binding = FragmentChooseVehicleBinding.inflate(inflater, container, false)
_mainBinding = ActivityMainBinding.inflate(layoutInflater)
mainBinding.appBarMain.appBarLogo.visibility = View.GONE //This has no effect in the UI
return binding.root
}
I checked with debugging and the visibility property on appBarLogo changed correctly and is the right value in onStart()/onResume() as well, but the image still appears in the UI.
Another thing I tried is to inflate the app bar view binding directly, like this:
override fun onStart() {
super.onStart()
val binding = AppBarMainBinding.inflate(layoutInflater)
binding.appBarLogo.visibility = View.GONE
}
Still no change in the UI; the image remains visible. The only thing that works is the old findViewById:
override fun onStart() {
super.onStart()
val appBarLogo = activity?.findViewById<ImageView>(R.id.appBarLogo)
appBarLogo?.visibility = View.GONE
}
Any idea what I'm doing wrong? Thanks.
Update: Here are the layout files (thanks Michael):
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"
tools:openDrawer="start">
<include
android:id="#+id/app_bar_main"
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="#dimen/nav_header_width"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#drawable/gradient_black"
app:itemIconTint="#color/white"
app:itemTextColor="#FFFFFF"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
app_bar_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/Theme.company.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#drawable/gradient_red"
app:popupTheme="#style/Theme.company.PopupOverlay">
<ImageView
android:layout_width="match_parent"
android:id="#+id/appBarLogo"
android:layout_height="wrap_content"
android:layout_marginLeft="70dp"
android:layout_marginRight="70dp"
app:srcCompat="#drawable/ic_logo_company" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I am trying to add drawerlayout in my fragment home. I am getting java.lang.IllegalArgumentException: DrawerLayout must be measured with MeasureSpec.EXACTLY. this error when I tried to attach drawer layout to my fragment.
I have root layout as constraint layout. Firstly I tried with root layout as drawerlayout still I wast getting this exception so I tried adding constraint layout to it but did not work.
It works when I give the hard coded value to height and width as 500dp.
But hard coded value cant be given as it will not be good practice for all devices size it will differ.
Below is my code
drawer layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/drawer"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/fragment_home"
android:visibility="visible" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_gravity="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="#+id/nav_header"
layout="#layout/nav_header" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fadeScrollbars="true"
android:scrollbars="none">
<include
android:id="#+id/menuItems"
layout="#layout/layout_navigation_menu" />
</ScrollView>
</LinearLayout>
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Home fragment layout
<?xml version="1.0" encoding="utf-8"?>
<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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fillViewport="true"
android:fitsSystemWindows="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include android:id="#+id/app_bar"
layout="#layout/app_bar_main"/>
<RelativeLayout
android:id="#+id/relative_accept"
android:layout_width="match_parent"
android:layout_height="#dimen/margin_55"
android:orientation="horizontal"
android:background="#color/green_500"
app:layout_constraintTop_toBottomOf="#id/app_bar">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:textColor="#color/white"
android:layout_marginLeft="#dimen/margin_16"
android:layout_marginStart="#dimen/margin_16"
android:layout_marginRight="#dimen/margin_16"
android:layout_marginEnd="#dimen/margin_16"
android:text="#string/accepting_orders"
android:fontFamily="#font/roboto_regular"
android:textSize="#dimen/text_size_15"
android:layout_alignParentLeft="true"
android:layout_height="wrap_content" />
<Switch
android:id="#+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:track="#drawable/switch_track_selector"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
tools:ignore="UseSwitchCompatOrMaterialXml" />
</RelativeLayout>
<FrameLayout
android:id="#+id/frameLayout_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/relative_accept">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="42dp"
android:layout_marginStart="#dimen/margin_16"
android:layout_marginLeft="#dimen/margin_16"
android:layout_marginTop="#dimen/margin_20"
android:layout_marginEnd="#dimen/margin_16"
android:layout_marginRight="#dimen/margin_16"
android:background="#drawable/grey_drawable"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:tabGravity="fill"
app:tabIndicatorHeight="0dp"
app:tabMode="fixed"
android:onClick="#{(v)->click.onClick(v)}"
app:tabBackground="#drawable/tab_selector"
app:tabSelectedTextColor="#color/white" />
</FrameLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="#+id/frameLayout_tab" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
Home fragment
class HomeFragment : BaseFragment() , View.OnClickListener{
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.drawer_layout_navigation_view, container, false)
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
init()
controlInit()
}
override fun init() {
val toggle = ActionBarDrawerToggle(
(activity as MainActivity),
drawer,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
)
drawer.addDrawerListener(toggle)
tabs.setupWithViewPager(view_pager)
bindViewPagerAdapter(view_pager, (activity as MainActivity))
bindViewPagerTabs(tabs, view_pager)
tabSettings()
}
private fun tabSettings() {
tabs.bringToFront()
view_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(
position: Int, positionOffset: Float, positionOffsetP: Int
) {
}
override fun onPageSelected(position: Int) {}
override fun onPageScrollStateChanged(i: Int) {}
})
}
private fun bindViewPagerAdapter(view: ViewPager?, mainActivity: MainActivity) {
val adapter = OrdersAdapter(view?.context!!, childFragmentManager)
view.adapter = adapter
}
private fun bindViewPagerTabs(view: TabLayout, pagerView: ViewPager?) {
view.setupWithViewPager(pagerView, true)
}
private fun controlInit() {
imageView_drawer.setOnClickListener(this)
}
#SuppressLint("WrongConstant")
override fun onClick(p0: View) {
when (p0.id) {
R.id.imageView_drawer -> {
drawer.openDrawer(Gravity.START)
}
}
}
companion object {
#JvmStatic
fun newInstance() =
HomeFragment().apply {}
}
}
Please help with this.Thank you....
Your layout actually worked just fine when I tested it so I am not sure if the issue lies with the layout. However your layout files are overly complex, you don't really need any of the nested layouts that you have and can achieve the same results without. ConstraintLayout was developed with the purpose of simplifying layout hierarchies so you should be able to just use that to organise your child views.
Also the NavigationView component is meant to be used to display a menu from a menu resource, not just to be used as a wrapper for your own. Either choose to display your own menu completely or use their implementation as intended. There is some nice documentation for this on the [Material Design website] here.
So may I suggest you try to cut down on nesting your layouts and then see whether this incidentally fixes your problem.
The hierarchy that you might want would probably look something like this:
drawer_layout.xml
<DrawerLayout>
<include layout="#layout/home" />
<NavigationView />
</DrawerLayout>
home.xml
<ScrollView>
<ConstraintLayout>
<include layout="#layout/app_bar_main"/>
<TextView />
<Switch />
<TabLayout />
<ViewPager />
</ConstraintLayout>
</ScrollView>
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>
I use Navigation Component in project. Trying to set up shared element transitions from recycler. And enter transition in the second fragment works fine, but when I return to the first fragment - there is no return transition.
I tried to explicitly set enter and return transitions in the first fragment like I did in the second like this
val transition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
sharedElementEnterTransition = transition
sharedElementReturnTransition = transition
but it didn't help.
Also tried to remove enter and exit fragment animations. For the second fragment enter transition works with animations, but who knows.
also tried to use the solution from this question, but in my case it didn't work.
https://stackoverflow.com/a/52922835/10951565
mainFragment
stickyAdapter.onItemClick = { event, imageView, textView ->
val args = bundleOf(EventDetailFragment.EVENT to event)
val extras = FragmentNavigatorExtras(
imageView to imageView.transitionName,
textView to textView.transitionName
)
findNavController().navigate(R.id.action_global_eventDetailFragment, args, null, extras)
}
in adapter onClick I set unique transition names for the views:
mainFragmentAdapter
eventImageView.setOnClickListener {
titleTextView.transitionName = "${event.title}$TRANSITION_TITLE"
eventImageView.transitionName = "${event.title}$TRANSITION_IMAGE"
onItemClick?.invoke(event, eventImageView, titleTextView)
}
in detailsFragment I get transition names from arguments (copypasted them to be sure there is no mistakes and for enter transition it worked)
I call postponeEnterTransition() in OnCreate method to wait until i can set transition names, sharedElementEnterTransition and sharedElementReturnTransition in onViewCreated and then call startPostponedEnterTransition()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
postponeEnterTransition()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.fragment_event_detail, container, false).apply {
val event = arguments?.getSerializable(EVENT) as Event?
toolbarImageView.transitionName = "${event?.title}$TRANSITION_IMAGE"
titleTextView.transitionName = "${event?.title}$TRANSITION_TITLE"
val transition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
sharedElementEnterTransition = transition
sharedElementReturnTransition = transition
startPostponedEnterTransition()
toolbar.setupWithNavController(findNavController())
event?.let {
Picasso.get()
.load("${EventGroupAdapter.BASE_SMALL_IMAGE_URL}${event.smallimage}")
.into(toolbarImageView)
}
}
}
main_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".view.activity.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="256dp"
android:background="?android:colorBackground"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="200dp"
android:fitsSystemWindows="true" />
<com.rd.PageIndicatorView
android:id="#+id/pageIndicatorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/viewPager"
android:layout_centerHorizontal="true"
android:layout_marginBottom="7dp"
app:piv_dynamicCount="true"
app:piv_interactiveAnimation="true"
app:piv_radius="3.5dp"
app:piv_selectedColor="#color/colorIndicatorSelected"
app:piv_unselectedColor="#color/colorIndicatorUnselected"
app:piv_viewPager="#id/viewPager" />
<include
android:id="#+id/horizontalScrollView"
layout="#layout/fragment_main_horizontal_scroll_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/viewPager" />
</RelativeLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:id="#+id/emptyMessage"
android:layout_marginTop="40dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layoutAnimation="#anim/layout_animation_from_bottom"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/ic_empty_events"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/empty_events_message"
android:textSize="18sp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="48dp"
android:nestedScrollingEnabled="true"
tools:listitem="#layout/fragment_main_event_item" />
</RelativeLayout>
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/programTextView"
android:layout_gravity="center"
android:visibility="gone"
tools:visibility="visible" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?android:colorBackground"
app:menu="#menu/bottom_navigation" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Please share your recipe of the return shared element transition with Navigation Component
I ran into this the other day where going from the MainFragment item to a DetailFragment animated fine, but the sharedElementReturnTransition wasn't working when pressing back.
The fix for me was to postpone the transition on the MainFragment. At first, I was trying to do so in onCreate, but onCreate isn't always called when going back, so the fix was to postpone it in onViewCreated (I would guess onCreateView might work too) and then start the transition once the RecyclerView is ready.
DetailFragment:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val transition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
sharedElementEnterTransition = transition
sharedElementReturnTransition = transition
}
MainFragment:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
postponeEnterTransition()
recycler_view.post { startPostponedEnterTransition() }
}