I'm kinda new to Android App Development. Well, I'm playing around with RecyclerView. I have a parent recyclerview with a modal layout. Now the modal layout has a recyclerview (child recyclerview). I have managed to create adapters and scroll the list of main recyclerview. Unfortunately I don't find a way to scroll the child recyclerview. Here is the code that I'm playing around:
I've already tried setting the adapter of child recyclerview in onBindViewHolder method of parent recyclerview adapter.
Also, I tried setting the attributes nestedScrollingEnabled=true, descendantFocusability=blocksDescendants and focusableInTouchMode=true for child recyclerView.
Here's my activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Parent recyclerview model (model.xml):
<?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="wrap_content"
android:layout_margin="16dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="Testing" />
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
android:background="#android:color/darker_gray"
android:layout_marginVertical="8dp"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/modalRecyclerView"
android:layout_width="wrap_content"
android:layout_height="100dp" />
</LinearLayout>
Child recyclerview model (child_modal.xml):
<?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="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Testing"/>
</LinearLayout>
In the MainActivity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerView.apply {
layoutManager = LinearLayoutManager(this#MainActivity, RecyclerView.VERTICAL, false)
adapter = ModalAdapter()
}
}
ModalAdapter:
class ModalAdapter : RecyclerView.Adapter<ModalAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context).inflate(R.layout.model, parent, false)
return ViewHolder(inflater)
}
override fun getItemCount(): Int {
return 5
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.view.modalRecyclerView.adapter = ChildModalAdapter()
holder.view.modalRecyclerView.layoutManager = LinearLayoutManager(holder.view.context, RecyclerView.VERTICAL, false)
}
class ViewHolder(val view: View): RecyclerView.ViewHolder(view)
}
ChildModalAdapter:
class ChildModalAdapter : RecyclerView.Adapter<ChildModalAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context).inflate(R.layout.child_modal, parent, false)
return ViewHolder(inflater)
}
override fun getItemCount(): Int {
return 10
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
}
class ViewHolder(val view: View): RecyclerView.ViewHolder(view)
}
Internal recyclerview doesn't scroll while the parent recyclerview scrolls fine. I'm trying to find a way to make the internal recyclerview to scroll along with parent recyclerview (I want both the recyclerviews to scroll).
Okay, I fixed this by setting a listener.
Here's the code below that fixed it:
val mScrollChangeListener = object : RecyclerView.OnItemTouchListener {
override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
when (e.action) {
MotionEvent.ACTION_MOVE -> {
rv.parent.requestDisallowInterceptTouchEvent(true)
}
}
return false
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}
modalRecyclerView.addOnItemTouchListener(mScrollChangeListener)
I've added this code in the onBindViewHolder() of parent RecyclerView's adapter.
Related
My RecyclerView is not able to find element's id. I tried to use findViewById but it is not working as my app gets crashed.
This is my Custom Adapter - MyRecyclerAdapter.kt:
class MyRecyclerAdapter(
private var notiList : ArrayList<NotificationClass>) :RecyclerView.Adapter<MyRecyclerAdapter.RecyclerViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_layout,parent,false)
return RecyclerViewHolder(itemView)}
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
//Problem Arise here
holder.itemView.titleView.text = notiList[position].title }
override fun getItemCount(): Int = notiList.size
class RecyclerViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView)
}
This is my item's Layout - item_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:elevation="30dp"
android:layout_margin="5dp"
app:cardCornerRadius="10dp" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/titleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/name"
android:textSize="25sp"
android:textColor="#color/black"
android:fontFamily="#font/raleway_bold"
android:maxLines="1"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp" />
<TextView
android:id="#+id/descView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/name"
android:textSize="20sp"
android:textColor="#color/black"
android:fontFamily="#font/raleway_semibold"
android:maxLines="3"
android:scrollbars="vertical"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
You haven't defined the ViewHolder for your RecyclerView. It should be like below:
class MyRecyclerAdapter(
private var notiList : ArrayList<NotificationClass>) :RecyclerView.Adapter<MyRecyclerAdapter.RecyclerViewHolder>(){
// Define below ViewHolder
internal inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var titleView: TextView = view.findViewById(R.id.titleView)
var descView: TextView = view.findViewById(R.id.descView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_layout,parent,false)
return RecyclerViewHolder(itemView)}
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
//Problem Arise here
holder.itemView.titleView.text = notiList[position].title }
override fun getItemCount(): Int = notiList.size
class RecyclerViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView)
}
Try not to access from android.R. Rather, try something like this:
CategoryAdapterHolder(LayoutInflater.from(parent.context)
.inflate(com.example.secondhand.R.layout.category_list, parent, false))
Why do I get a NullPointerException in my ViewHolder's bindItems() method?
I've highlighted the line where I get the NullPointerException. The blogpost_author ID exists, as you can see in the XML, so what's the problem here? How is findViewById<TextView>(R.id.blogpost_author) returning null?
Adapter and ViewHolder code:
class BlogPostAdapter(val blogList: ArrayList<BlogPost>) : RecyclerView.Adapter<BlogPostAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) : BlogPostAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.blog_post_list, parent, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return blogList.size
}
override fun onBindViewHolder(holder: BlogPostAdapter.ViewHolder, position: Int) {
holder.bindItems(blogList[position])
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindItems(blogPost: BlogPost) {
val blogPostAuthor = itemView.findViewById<TextView>(R.id.blogpost_author) // THIS LINE - NULL POINTER EXCEPTION
val blogPostTitle = itemView.findViewById<TextView>(R.id.blogpost_title)
blogPostAuthor.text = blogPost.author
blogPostTitle.text = blogPost.title
}
}
}
Activity code:
class BlogPostListActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.blog_post_list)
// Get the RecyclerView from XML itself
val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
// Add a layout manager - What does a layout manager do?
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL, false)
// Create an array list to store blogposts using the the data class blogPost
val blogPosts = ArrayList<BlogPost>()
// Add some dummy data to the list
blogPosts.add(BlogPost(123, "First Blog Post", "John"))
blogPosts.add(BlogPost(456, "Second Blog Post", "Bob"))
blogPosts.add(BlogPost(789, "Third Blog Post", "Mary"))
// Create an adapter
val adapter = BlogPostAdapter(blogPosts)
// Add the adapter to the recyclerview
recyclerView.adapter = adapter
}
}
Kotlin data class:
data class BlogPost(val id: Int, val title: String, val author: String)
XML for RecyclerView:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.topzap.android.kotlinlistapptest.BlogPostListActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
XML for CardView layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/blogpost_author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="AuthorPlaceHolder"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Large"
/>
<TextView
android:id="#+id/blogpost_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="TitlePlaceHolder"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
You may be inflating the wrong layout within your RecyclerView.
This line within your onCreateViewHolder method:
val v = LayoutInflater.from(parent.context).inflate(R.layout.blog_post_list, parent, false)
You are inflating the blog_post_list.xml, which I'm assuming is the wrong layout file due to the fact you're also inflating that layout within your BlogPostListActivity here:
setContentView(R.layout.blog_post_list)
So when this line is called:
val blogPostAuthor = itemView.findViewById<TextView>(R.id.blogpost_author)
It is looking for the id 'blogpost_author' within R.layout.blog_post_list and as you can see there is no blogpost_author TextView within that layout so it returns null.
To sort it out, it should be straight forward and just change the layout resource that you're assigning to each ViewHolder within your onCreateViewHolder method with the correct layout for your CardView layout.
Which means the line should read something like:
val v = LayoutInflater.from(parent.context).inflate(R.layout.your_card_layout, parent, false)
I'm having troubles trying to display a recycler which contains more than 1 ViewHolder, i was testing and sending a custom List which contains only data to display a list of the 1st ViewType.
payments.add(Purchase(0,R.drawable.ic_cart,"",""))
payments.add(Purchase(0,R.drawable.ic_favorite,"",""))
payments.add(Purchase(0,R.drawable.ic_arrow_back,"",""))
This is the BottomSheetClass
class PaymentStepsFragment : SuperBottomSheetFragment() {
val payments = ArrayList<Any>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.fragment_steps_payment, container, false)
}
private fun RecyclerAnimator(recyclerView: RecyclerView, adapter: PurchaseViewAdapter) {
val itemAnimator = DefaultItemAnimator()
itemAnimator.addDuration = 1000
itemAnimator.removeDuration = 1000
recyclerView.itemAnimator = itemAnimator
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(context)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
payments.add(Purchase(0,R.drawable.ic_cart,"",""))
payments.add(Purchase(0,R.drawable.ic_favorite,"",""))
payments.add(Purchase(0,R.drawable.ic_arrow_back,"",""))
val recycler = view.findViewById<RecyclerView>(R.id.payment_rv)
val adapter = PurchaseViewAdapter(payments, context!!)
RecyclerAnimator(recycler, adapter)
}
override fun getCornerRadius() = context!!.resources.getDimension(R.dimen.sheet_rounded_corner)
override fun getStatusBarColor() = Color.RED
}
and my RecyclerViewAdapter.
constructor(list: List<Any>, context: Context) : this() {
this.list = list
this.context = context
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType){
0 -> {
context = parent.context
val menuItemLayoutView = LayoutInflater.from(parent.context).inflate(R.layout.fragment_card_payment, parent, false)
PaymentViewHolder(menuItemLayoutView)
}
else -> {
context = parent.context
val menuItemLayoutView = LayoutInflater.from(parent.context).inflate(R.layout.fragment_card_payment, parent, false)
PaymentViewHolder(menuItemLayoutView)
}
}
}
override fun getItemViewType(position: Int): Int {
val data = list?.get(position) as Purchase
return data.type
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(holder.itemViewType){
0 -> {
val holder_payment = holder as PaymentViewHolder
val menuItem = list!![position] as Purchase
holder_payment.paymentTimeline.marker = ContextCompat.getDrawable(context!!,menuItem.resource)
}
else -> {
val holder_payment = holder as PaymentViewHolder
val menuItem = list!![position] as Purchase
holder_payment.paymentTimeline.marker = ContextCompat.getDrawable(context!!,menuItem.resource)
}
}
}
However when I send the information to be displayed, it always return the list empty, I don't know where is the problem, the data it's seems to be sent nicely.
And the constructor of the RecyclerViewAdapter prints the List obtained, but that list won't display the DesiredViewHolders to be inflated in the RecyclerView...
As requested I added the Layout where I call the RecyclerView
<?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"
android:id="#+id/view_bottom_sheet_attributes"
tools:background="#color/colorWhite">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_height="50dp"
android:id="#+id/text_attributes_heading"
android:gravity="center"
android:paddingLeft="12dp"
android:text="TEMPORAL"
android:textSize="18sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<View
android:layout_width="0sp"
android:layout_height="1dp"
android:background="#color/colorDivider"
app:layout_constraintTop_toBottomOf="#id/text_attributes_heading"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/image_toggle"
android:layout_marginRight="5dp"
app:srcCompat="#drawable/ic_expand_less_black_24dp"
app:layout_constraintTop_toTopOf="#id/text_attributes_heading"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="#id/text_attributes_heading"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/payment_rv"
android:fillViewport="true"
android:padding="5dp"
android:clipToPadding="false"
app:layout_constraintTop_toBottomOf="#id/text_attributes_heading"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="#id/button_apply">
</androidx.recyclerview.widget.RecyclerView>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:background="#color/colorDivider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/payment_rv"/>
<com.google.android.material.button.MaterialButton
android:layout_width="match_parent"
android:layout_height="45dp"
android:id="#+id/button_apply"
android:layout_margin="5dp"
android:text="#string/purchase"
style="#style/Widget.MaterialComponents.Button"
android:insetTop="0dp"
android:insetBottom="0dp"
app:cornerRadius="0dp"
app:layout_constraintTop_toBottomOf="#id/payment_rv"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Also the type of the ViewHolder it seems that don't reach the override function...
Check your layout XML it looks like the RecyclerView view is hidden by other views
I have this drawer which opens normally but the scrolling in it is very slow, and I don't know why knowing that the image it has on top of it is not HD image, and available in the 4 sizes, I've done various examples in Java and it was fine, I wonder if the issue is that I'm using Kotlin in the adapter.
I would appreciate any help.
The activity's layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:fitsSystemWindows="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/gradient_background"
android:orientation="vertical">
<include
android:id="#+id/top"
layout="#layout/top_bar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize" />
<TextView
android:layout_below="#+id/top"
android:id="#+id/tvTradesTicker"
android:layout_width="match_parent"
android:layout_height="#dimen/trades_ticker_height"
android:background="#color/colorPrimaryLight"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:focusable="true"
android:freezesText="true"
android:marqueeRepeatLimit="marquee_forever"
android:padding="#dimen/small_margin"
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="#color/darkGray"
android:textSize="#dimen/font"
android:visibility="visible" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rvGrid"
android:layout_below="#+id/tvTradesTicker"
android:layout_above="#+id/llFooter"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<include
layout="#layout/footer"
android:id="#+id/llFooter"
android:layout_width="match_parent"
android:layout_height="#dimen/footer_height"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/white"
android:fitsSystemWindows="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:paddingTop="#dimen/big_margin_padding"
android:orientation="vertical">
<include
layout="#layout/item_drawer_header"
android:id="#+id/header"
android:background="#color/white"
android:layout_width="match_parent"
android:layout_height="#dimen/drawer_header_height" />
<ListView
android:id="#+id/lvItems"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white"
android:divider="#android:color/transparent"
android:paddingTop="#dimen/small_margin" />
</LinearLayout>
</android.support.design.widget.NavigationView>
The Drawer's Adapter:
class DrawerListAdapter : BaseAdapter {
private var drawerItems: MutableList<DrawerItem> = mutableListOf()
private var context: Context? = null
constructor(context: Context, notesList: MutableList<DrawerItem>) : super() {
this.drawerItems = notesList
this.context = context
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
val view: View?
val vh: ViewHolder
val inflater = LayoutInflater.from(context)
val type = getItemViewType(position)
if (convertView == null) {
view = if (type == 0){
inflater.inflate(R.layout.item_drawer_section, parent, false)
}else{
inflater.inflate(R.layout.item_drawer_child, parent, false)
}
vh = ViewHolder(view)
view.tag = vh
} else {
view = convertView
vh = view.tag as ViewHolder
}
val drawerItem = drawerItems[position]
vh.name.text = drawerItem.name
if (type == 0){
vh.rel.setBackgroundColor(ContextCompat.getColor(context!!, R.color.blue))
vh.name.setBackgroundColor(ContextCompat.getColor(context!!, R.color.colorAccent))
vh.name.setTextColor(ContextCompat.getColor(context!!, R.color.white))
}else if (type == 1){
vh.rel.setBackgroundColor(ContextCompat.getColor(context!!, R.color.white))
vh.name.setBackgroundColor(ContextCompat.getColor(context!!, R.color.white))
vh.name.setTextColor(ContextCompat.getColor(context!!, R.color.colorPrimary))
vh.separator.visibility = View.VISIBLE
}else{
vh.rel.setBackgroundColor(ContextCompat.getColor(context!!, R.color.white))
vh.name.setBackgroundColor(ContextCompat.getColor(context!!, R.color.white))
vh.name.setTextColor(ContextCompat.getColor(context!!, R.color.colorPrimary))
vh.separator.visibility = View.GONE
}
Actions.overrideFonts(context!!, vh.rel)
return view
}
override fun getItem(position: Int): DrawerItem {
return drawerItems[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return drawerItems.size
}
override fun getItemViewType(position: Int): Int {
if (drawerItems[position].isHeader)
return 0
else if (!drawerItems[position].isLast)
return 1
else
return 2
}
override fun getViewTypeCount(): Int {
return 3
}
}
private class ViewHolder(view: View) {
val rel: RelativeLayout = view.findViewById(R.id.rel) as RelativeLayout
val name: TextView = view.findViewById(R.id.name) as TextView
val separator = view.findViewById<View>(R.id.separator)
}
What should I change, the activity layout, or the adapter or what i realy have no idea.
EDIT
I set the visibility of the marquee text view in the layout to gone, and everything worked just fine, does anybody know why? because I don't want to replace this text view with a horizontal recycler view
SOLVED.
Changed the approach completely, I stopped the marquee and applied cross fade animation to the text view, with a handler that changes the object being set in the text view at each iteration, and now it looks perfect and way more elegnat
I am trying to do the following:
In activity, replace the container with a fragment (TestFragment)
This fragment's layout contains a container which is replaced by another fragment (TestSubFragment)
Clicking on the TestSubFragment makes the activity add a new TestFragment over the root container
TestActivity.kt
class TestActivity : AppCompatActivity(), TestSubFragment.OnFragmentInteractionListener {
override fun onFragmentInteraction(id: Int) {
supportFragmentManager.beginTransaction().add(R.id.container, TestFragment.newInstance(id)).addToBackStack(null).commit()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
supportFragmentManager.beginTransaction().replace(R.id.container, TestFragment.newInstance(1)).addToBackStack(null).commit()
}
}
TestFragment.kt
class TestFragment : Fragment() {
private var id: Int? = null
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val v = inflater!!.inflate(R.layout.fragment_test, container, false)
activity.supportFragmentManager.beginTransaction().replace(R.id.sub_fragment_container, TestSubFragment.newInstance(id!!)).commit()
return v
}
companion object {
fun newInstance(id: Int): TestFragment {
val fragment = TestFragment()
fragment.id = id
return fragment
}
}
}
TestSubFragment.kt
class TestSubFragment : Fragment() {
private var mListener: OnFragmentInteractionListener? = null
private var id: Int? = null
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val v = inflater!!.inflate(R.layout.fragment_sub_test, container, false)
v.id_text.text = id.toString()
v.id_text.setOnClickListener { _ -> mListener?.onFragmentInteraction(v.id_text.text.toString().toInt() + 1) }
return v
}
override fun onAttach(context: Context?) {
super.onAttach(context)
if (context is OnFragmentInteractionListener) {
mListener = context
}
}
interface OnFragmentInteractionListener {
fun onFragmentInteraction(id: Int)
}
companion object {
fun newInstance(id: Int): TestSubFragment {
val fragment = TestSubFragment()
fragment.id = id
return fragment
}
}
}
activity_test.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ckl.happens.TestActivity">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
fragment_test.xml
<FrameLayout 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"
android:background="#ffffff"
tools:context="ckl.happens.TestFragment">
<FrameLayout
android:id="#+id/sub_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</FrameLayout>
fragment_sub_test.xml
<FrameLayout 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"
android:background="#ffffff"
tools:context="ckl.happens.TestFragment">
<TextView
android:id="#+id/id_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment" />
</FrameLayout>
Problem is that the replace fragment line in TestFragment.kt is finding the first R.id.sub_fragment_container from the xml hierarchy so it is replacing the incorrect container instead of the last/new container.
I tried adding tag in fragmenttransaction or change R.id.sub_fragment_container to v.sub_fragment_container.id but no luck.
I don't want to change add() to replace() in onFragmentInteraction because the fragment will be recreated and I want to keep everything in the fragment unchanged when the user back to that fragment.
I can't find detailed article on nesting fragments for my case.
I am working with Kotlin but I can also understand Java. Thank you!
I solved my problem without getting the new container id.
I decided to remove fragmenttransaction and add the fragment in the xml. Then in the fragment (parent fragment) that contains the sub-fragment, get the sub-fragment with childFragmentManager.findFragmentById(R.id.fragment). Finally update the content of the sub-fragment from the parent fragment.
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
val fragment1 = TestFragment.newInstance(1)
supportFragmentManager.beginTransaction().replace(R.id.container, fragment1).commit()
val fragment2 = TestFragment.newInstance(2)
supportFragmentManager.beginTransaction().add(R.id.container, fragment2).addToBackStack(null).commit()
val fragment3 = TestFragment.newInstance(3)
supportFragmentManager.beginTransaction().add(R.id.container, fragment3).addToBackStack(null).commit()
}
}
class TestFragment : Fragment() {
private var id: Int? = null
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val v = inflater!!.inflate(R.layout.fragment_test, container, false)
val subFragment = childFragmentManager.findFragmentById(R.id.fragment) as TestSubFragment
subFragment.view?.findViewById<TextView>(R.id.id_text)?.text = id.toString()
return v
}
companion object {
fun newInstance(id: Int): TestFragment {
val fragment = TestFragment()
fragment.id = id
return fragment
}
}
}
class TestSubFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater!!.inflate(R.layout.fragment_sub_test, container, false)
}
}
activity_test.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ckl.happens.TestActivity">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
</FrameLayout>
</android.support.constraint.ConstraintLayout>
fragment_test.xml
<FrameLayout 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"
android:background="#ffffff"
tools:context="ckl.happens.TestFragment">
<fragment
android:id="#+id/fragment"
android:name="ckl.happens.TestSubFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
fragment_sub_test.xml
<FrameLayout 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"
android:background="#ffffff"
tools:context="ckl.happens.TestFragment">
<TextView
android:id="#+id/id_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="" />
</FrameLayout>