Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm trying to get a popup to show up when I press a button. I wanted to make sure it even shows up before working on the details but the app just crashes when i press it. The commented block is what I originally intended the button to do (just adding an item to the recyclerview) but I decided I wanted to do something a bit different. It only had the problem of crashing when I started adding the popup window stuff. The app still runs fine even if I remove the popup window stuff and leave the commented block commented out. So I don't know if the listadapter class is relevant but ill just include it.
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var listAdapter: ListAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
listAdapter = ListAdapter(mutableListOf())
recyclerView.adapter = listAdapter
recyclerView.layoutManager = LinearLayoutManager(this)
btn_add.setOnClickListener {
/*
//get text from textbox
val itemText = et_reminder.text.toString()
if (itemText.isNotEmpty()){
//create item with text
val item = Item (itemText)
//add to list
listAdapter.addItem((item))
//clear textbox
et_reminder.text.clear()
}*/
val view : View = LayoutInflater.from(applicationContext).inflate (R.layout.popup_s,null)
val popup: PopupWindow = PopupWindow(view, 250, 250,true)
popup.showAtLocation(view, Gravity.NO_GRAVITY, 0,0)
}
}
}
ListAdapter.kt
class ListAdapter(
private val items: MutableList<Item>
): RecyclerView.Adapter<ListAdapter.ListViewHolder>()
{
class ListViewHolder(itemView: View):RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
val itemView: View =
LayoutInflater.from(parent.context).inflate (R.layout.list_item, parent, false)
return ListViewHolder(itemView)
}
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
val curr_item = items [position]
holder.itemView.apply {
tv_reminder.text = curr_item.text;
cb_check.isChecked = curr_item.checked
cb_check.setOnCheckedChangeListener { _, isChecked ->
//changing status of checked
curr_item.checked = isChecked
for (i in items.indices.reversed()) {
if (items[i].checked) {
items.removeAt(i)
notifyItemRemoved(i)
}
}
}
}
}
override fun getItemCount(): Int {
return items.size
}
fun addItem (new_item: Item){
items.add (new_item)
notifyItemInserted(items.size - 1)
}
}
activity_main.xml
<?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"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#color/basically_black"
app:layout_constraintBottom_toTopOf="#+id/et_reminder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="#+id/et_reminder"
android:layout_width="0dp"
android:layout_height="45dp"
android:hint="Reminder"
android:textSize="20sp"
android:textColorHint="#color/white_purple"
android:textColor="#color/white_purple"
android:background="#color/basically_black"
android:paddingStart="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/btn_add"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/recyclerView"/>
<Button
android:id="#+id/btn_add"
android:layout_width="45dp"
android:layout_height="wrap_content"
android:text="+"
android:textSize="20sp"
android:background="#color/basically_black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
list_item.xml
<?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="55dp"
android:paddingStart="10dp">
<TextView
android:id="#+id/tv_reminder"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingTop="0dp"
android:text="temp"
android:textColor="#color/white_purple"
android:textSize="20sp"
android:maxLines="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/cb_check"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="#+id/cb_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
popup_s.xml
<?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"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<EditText
android:id="#+id/et_r"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Reminder"
android:textColor="#color/white_purple"
android:textColorHint="#color/gray"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0">
</EditText>
</androidx.constraintlayout.widget.ConstraintLayout>
I think that happen because you are trying to pass applicationContext it will give you Unable to add window -- token null is not valid; is your activity running?
try to pass the current activity context instead cause PopupWindow can only be attached to an Activity
val view : View = LayoutInflater.from(this).inflate (R.layout.popup_s,null)
val popup = PopupWindow(view, 250, 250,true)
popup.showAtLocation(view, Gravity.NO_GRAVITY, 0,0)
Related
I created the image slider using smarteist image slider github library and it's working fine. I wanted to show 3 items at a time but Item occupies whole space and visible only 1 item. I also tried recyclerview to achieve this thing but can't get same feel as image slider. So guide me how to achieve it.
Expected
To show 3 items at a time before slide.
what I had done
val partner_recyclerView: SliderView = findViewById(R.id.partnership_slider)
var partnerAdapter: PartnerAdapter = PartnerAdapter(partnerList)
partner_recyclerView.autoCycleDirection = SliderView.LAYOUT_DIRECTION_LTR
partner_recyclerView.setSliderAdapter(partnerAdapter)
partner_recyclerView.scrollTimeInSec = 3
partner_recyclerView.isAutoCycle = true
partner_recyclerView.startAutoCycle()
Item_layout
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="150dp"
android:layout_height="80dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="5dp"
android:layout_marginTop="8dp"
app:cardElevation="8dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="8dp"
app:cardCornerRadius="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/myPartnerLogo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:contentDescription="#string/app_name"
android:scaleType="fitXY"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
</androidx.cardview.widget.CardView></androidx.constraintlayout.widget.ConstraintLayout>
Main_Layout
<com.smarteist.autoimageslider.SliderView
android:id="#+id/partnership_slider"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_centerInParent="true"
app:sliderAnimationDuration="600"
app:sliderAutoCycleDirection="back_and_forth"
app:sliderScrollTimeInSec="1"
android:padding="10dp"
app:layout_constraintBottom_toTopOf="#+id/constraintLayout3"
app:layout_constraintEnd_toEndOf="#+id/constraintLayout3"
app:layout_constraintStart_toStartOf="#+id/constraintLayout3"
app:layout_constraintTop_toTopOf="#+id/constraintLayout3"/>
Adapter_class
class PartnerAdapter (val mList: ArrayList<PartnershipData>) :
SliderViewAdapter<PartnerAdapter.SliderViewHolder>() {
override fun getCount(): Int {
return mList.size
}
override fun onCreateViewHolder(parent: ViewGroup?): PartnerAdapter.SliderViewHolder {
val inflate: View = LayoutInflater.from(parent!!.context).inflate(R.layout.partner_item, null)
return PartnerAdapter.SliderViewHolder(inflate)
}
override fun onBindViewHolder(viewHolder: PartnerAdapter.SliderViewHolder?, position: Int) {
if (viewHolder != null) {
// if view holder is not null we are simply
// loading the image inside our image view using glide library
Glide.with(viewHolder.itemView).load(mList.get(position).pwa_iconpng).fitCenter()
.into(viewHolder.myPartnerLogo)
}
}
class SliderViewHolder (itemView: View?) : SliderViewAdapter.ViewHolder(itemView) {
val myPartnerLogo: ImageView = itemView!!.findViewById(R.id.myPartnerLogo)
}}
For better understanding
Expected
Problem
So I am trying to create a simple Note App, where the user gives data, gets stored in a database, and is displayed using a recycler view. Up until now, I can confirm that data is being stored in my database, and that data is also being retrieved from it and being initialized to a variable in the adapter class, but for some reason, the Adapter's OnCreateViewHolder(), OnBindViewHolder() and getItemCount() functions are not being called even after notifying the adapter of the change in data. This is my MainActivity and Adapter class.
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: NoteViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val noteAdapter = NotesRVAdapter(this)
notesRV.adapter = noteAdapter
notesRV.layoutManager = LinearLayoutManager(this)
viewModel = ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(application)).get(NoteViewModel::class.java)
//access getAllNotes from NoteViewModel class from created instance
viewModel.getAllNotes.observe(
this,
Observer { list ->
list?.let {
Log.d("TAG","Observing")
NotesRVAdapter(this).updateList(it as ArrayList<NoteEntity>)
// Toast.makeText(this,"$it",Toast.LENGTH_LONG).show()
}
},
)
}
fun createNote(view: View) {
val intent = Intent(this,SecondActivity::class.java) // for creating a note
startActivity(intent)
}
}
Adapter Class
class NotesRVAdapter(private val context: Context) : RecyclerView.Adapter<NotesRVAdapter.NotesVH>() {
private var noteItem = ArrayList<NoteEntity>()
inner class NotesVH(noteView: View): RecyclerView.ViewHolder(noteView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotesVH {
val view = LayoutInflater.from(parent.context).inflate(R.layout.note_item,parent,false)
return NotesVH(view)
}
override fun onBindViewHolder(holder: NotesVH, position: Int) {
holder.itemView.Heading.text = noteItem[position].heading
holder.itemView.Description.text = noteItem[position].text
holder.itemView.Priority.text = noteItem[position].priority.toString()
}
override fun getItemCount(): Int {
return noteItem.size
}
fun updateList(list: ArrayList<NoteEntity>){
noteItem.clear()
noteItem.addAll(list)
// Toast.makeText(context,"${noteItem[0].text}",Toast.LENGTH_LONG).show()
notifyDataSetChanged()
}
}
The updateList function is getting called in mainactivity and the list is being passed in the noteitem and the toast also works, but that's it. All the override functions seem to be not working as I tried running a Log statement in them, but there was no entry for any Log in the Logcat.
I don't think there's a problem in the XML file as I could see the preview using the tools statement, but if someone needs to check it, here it is:
note_item.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="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:paddingHorizontal="30dp"
android:paddingVertical="30dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="#+id/Heading"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintRight_toLeftOf="#id/Priority"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text = "Note Heading"
android:textSize="35sp"
android:textStyle="bold"
android:textColor="#color/black"
/>
<TextView
android:id="#+id/Description"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/Heading"
app:layout_constraintRight_toLeftOf="#id/Priority"
tools:text="Description"
android:textSize="25sp"
android:textColor="#color/black"
/>
<TextView
android:id="#+id/Priority"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="1"
android:textSize="60sp"
android:textColor="#color/black"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
main_activity.xml
<?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"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/notesRV"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="0dp"
android:layout_height="0dp"
tools:listitem="#layout/note_item"
/>
<ImageView
android:id="#+id/createNote"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginBottom="80dp"
android:layout_marginRight="40dp"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="#drawable/ic_baseline_add_24"
android:onClick="createNote"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
I would appreciate it if someone could help me with this issue. Thanks!
you are creating a new adapter instance here which is not attached to your recyclerview
NotesRVAdapter(this).updateList(it as ArrayList<NoteEntity>)
change it to the one attached to your recyclerview and that will be
noteAdapter.updateList(it as ArrayList<NoteEntity>)
So I'm fairly new to Kotlin.
I am trying to create an onClickListener on an image button to open the share interface, so that the particular video from the recyclerView can be shared via SMS, etc.
I followed various tutorials on how to do this as I am trying to execute this within a fragment, and the app just keeps crashing when I try to open the fragment in question.
I get the following error
java.lang.ClassCastException: java.lang.Integer cannot be cast to android.widget.ImageButton
Here is what my fragment code looks like:
SearchFragment.kt
class SearchFragment : Fragment(), View.OnClickListener
{
private var layoutManager: RecyclerView.LayoutManager? = null
private var adapter: RecyclerView.Adapter<ClipAdapter.ViewHolder>? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View
{
val rootView = inflater.inflate(R.layout.fragment_search, container, false)
loadData()
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
{
val shareBtn = view.findViewById<ImageButton>(R.id.button_to_share)
shareBtn.setOnClickListener(this)
}
private fun loadData()
{
val service = TwitchServiceBuilder.buildService(TwitchService::class.java)
val requestCall = service.getClips("anerdfails")
requestCall.enqueue(object : Callback<List<Clip>>
{
override fun onResponse(
call: Call<List<Clip>>,
response: Response<List<Clip>>
)
{
if (response.isSuccessful)
{
//process data
recyclerView.layoutManager = GridLayoutManager(activity, 2)
recyclerView.adapter = ClipAdapter(response.body()!!)
} else
{
//output alert
AlertDialog.Builder(activity!!)
.setTitle("API error")
.setMessage("Response, but something went wrong ${response.message()}")
.setPositiveButton(android.R.string.ok) { _, _ -> }
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
}
}
override fun onFailure(call: Call<List<Clip>>, t: Throwable)
{
//process failure
AlertDialog.Builder(activity!!)
.setTitle("API error")
.setMessage("No response, and something went wrong $t")
.setPositiveButton(android.R.string.ok) { _, _ -> }
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
}
})
}
override fun onClick(v: View?)
{
Toast.makeText(activity, "Its toast!", Toast.LENGTH_SHORT).show()
}
}
And here are my 2 layouts for the RecyclerView:
fragment_search.xml
<?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:paddingStart="15dp"
android:paddingTop="?attr/actionBarSize"
android:paddingEnd="15dp"
tools:context=".ui.search.SearchFragment">
<androidx.appcompat.widget.SearchView
android:background="#drawable/search_bar"
android:id="#+id/clipSearch"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="5dp"
android:focusable="true"
android:focusableInTouchMode="true"
app:layout_constraintBottom_toTopOf="#+id/recyclerView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="75dp"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/clipSearch" />
</androidx.constraintlayout.widget.ConstraintLayout>
clip_layout.xml
<?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="wrap_content"
tools:context=".ui.search.SearchFragment">
<VideoView
android:id="#+id/videoClip"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
app:layout_constraintDimensionRatio="w,2:3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/txtTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/videoClip"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/txtChannel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/txtTitle"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/txtGame"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/txtChannel"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/txtViews"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/txtGame"
tools:ignore="HardcodedText" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="30dp"
android:orientation="horizontal"
android:weightSum="2"
android:layout_marginTop="15dp"
app:layout_constraintTop_toBottomOf="#+id/txtViews">
<ImageButton
android:id="#+id/favouriteButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#null"
android:scaleType="fitCenter"
android:src="#drawable/ic_baseline_favorite_border_24" />
<ImageButton
android:id="#+id/button_to_share"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#null"
android:scaleType="fitCenter"
android:src="#drawable/ic_baseline_share_24" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Seems like a simple mistake on my part, but I'm pulling my hair out trying to work out what I've done wrong to cause the error on loading.
Any help would be appreciated.
I see you're trying to find the button "ShareBtn" inside the fragment which is totally wrong.
the "ShareBtn" doesn't belong to the fragment, it belongs to the viewHolder which you have created inside "ClipAdapter"
What you need to do is creating an interface inside "ClipAdapter" and create an object from it inside the Adapter
then call the method which is should the clickListener delegates the click to it
lastly, you should implement it inside the fragment and put whatever logic you want
This link will help you implement it
You are casting ID of view which is an Integer to ImageButton which is a View in this line
val shareBtn = R.id.button_to_share as ImageButton
You should use this instead
val shareBtn = findViewById<ImageButton>(R.id.button_to_share)
UPDATE
Also you should find views after fragment view got created. It means you should call `findViewById` inside `onViewCreated` and not inside `onCreateView`. If you try to find views before view of fragment gets created then you get `NullPointerException` since there is no view yet.
I've made a little sample of something I'm trying to do in a real app, and I can't figure out how to solve my issue. The current solution looks like this.
So I have a vertical list of movie categories, where within each genre, I have a horizontal list of movies. The first row, is showing The Exorcist as the first element, but it's not centered. The second row in Action, shows how it looks when I've scrolled a bit to the right. Last row is showing how the end of the row looks like.
I'd like to have the first and last of the rows, to be centered as well when they're "selected".
My main activity looks like this:
<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">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/moviesListRecyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="#layout/movie_category_item_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
The movie_category_item_view looks like this:
<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:id="#+id/movieListLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/movieCategoryTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="40dp"
android:textColor="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Horror" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/moviesRecyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:orientation="horizontal"
android:visibility="visible"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/movieCategoryTitle"
tools:listitem="#layout/movie_horizontal_item_view" />
</androidx.constraintlayout.widget.ConstraintLayout>
And the movie_horizontal_item_view like this:
<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="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/movieTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="#android:color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Horror" />
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/image"
android:layout_width="237dp"
android:layout_height="209dp"
android:background="#android:color/black"
android:src="#drawable/ic_launcher_foreground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/movieTitle"
tools:src="#drawable/ic_launcher_foreground" />
</androidx.constraintlayout.widget.ConstraintLayout>
Hopefully what I'm asking for makes sense!
In case you want to try it out for yourself and see what I mean, it can be found on github here
use carouselview.CarouselView
<alirezat775.lib.carouselview.CarouselView
android:id="#+id/carousel_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"/>
the adapter
class MyAdapter(var ctx: Context) : CarouselAdapter() {
private var vh: CarouselViewHolder? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CarouselViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.home_list_item, parent, false)
vh = MyViewHolder(v)
return vh as MyViewHolder
}
override fun onBindViewHolder(holder: CarouselViewHolder, position: Int) {
}
inner class MyViewHolder(itemView: View) : CarouselViewHolder(itemView) {
}
}
the activity
class MainActivity : AppCompatActivity() {
var carousel: Carousel? = null
val adapter = MyAdapter(this)
override fun onCreate(savedInstanceState: Bundle?) {
carousel = Carousel(this, carousel_view, adapter)
carousel!!.setOrientation(CarouselView.HORIZONTAL, false)
// carousel!!.autoScroll(true, 5000, true)
// carousel!!.scaleView(true)
}
}
I'm currently working on a UI that looks like this
The blue part is a ConstraintLayout while the purple part is a RecyclerView inside it (it's a RecyclerView because it's content are dynamic based on service response).
I'm setting onClick handler on the ConstraintLayout that would take the user to another page. The problem is the RecyclerView is consuming the clicks and not forwarding it to its parent. Thus onClick handler works for the blue area, but not for the purple area.
I tried setting android:clickable="false" and android:focusable="false" in the RecyclerView but it still won't propagate the clicks to its parent.
One solution I came across is to extend from ConstraintLayout and override onInterceptTouchEvent() to return true. However I have a strict requirement in my project to not create custom widgets, so I cannot use this solution.
Is there a way to tell RecyclerView to stop consuming touch events?
Activity layout:
<FrameLayout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_margin="16dp"
android:background="#42d7f4"
android:onClick="navigate"
android:padding="16dp">
<TextView
android:id="#+id/headerText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="FRUITS"
android:textSize="36sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/itemsList"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#9f41f2"
android:clickable="false"
android:focusable="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
Item layout:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/itemText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:clickable="false"
android:focusable="false" />
Activity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rcView = findViewById<RecyclerView>(R.id.itemsList)
rcView.layoutManager = LinearLayoutManager(this)
val items = listOf("Apple", "Banana", "Oranges", "Avocado")
rcView.adapter = ItemAdapter(items)
}
fun navigate(view: View) {
Toast.makeText(this, "Navigating to details page", Toast.LENGTH_SHORT)
.show()
}
}
class ItemAdapter(private val data: List<String>) : RecyclerView.Adapter<ItemViewHolder>() {
override fun getItemCount(): Int = data.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return ItemViewHolder(view)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.bind(data[position])
}
}
class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val itemTv: TextView = view.findViewById(R.id.itemText)
fun bind(item: String) {
itemTv.text = item
}
}
If you freeze the layout after you've set the adapter it no longer swallows clicks:
recyclerView.isLayoutFrozen = true // kotlin
recyclerView.setLayoutFrozen(true); // java
Just keep in mind if you need to change the data in the adapter you have to unfreeze the layout before you call notifyDataSetChanged and then re-freeze the layout. I don't love this solution but it's the only one that worked for me.
One way to approach this is to set the RecyclerView row with a click listener and to disable clicks and long clicks on the children of the RecyclerView row as follows:
ConstraintLayout: `android:onClick="navigate"`
For the item layout: `android:onClick="navigate"`
TextView: android:clickable="false"
android:longClickable="false"
(etc. for all children of the row)
I think what is missing is to make the TextView not long clickable.
You can set your RecyclerView focus to false.
recyclerView.setFocusable(false);
And/Or set its rows view.setFocusable(false);
EDIT
If you want to give the ConstraintLayout the focus
layout.setFocusable(true);
layout.setClickable(true);
//
// add click listener and event ....
//
For more information please refer to the official documentation provided by Google
Hope this helps, cheers
Probably the easiest way to completely block interaction with anything inside a single view is to put a transparent view over it that intercepts all touch events. You can set click on that view manage all the functionality through that view.
For example like this
<FrameLayout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_margin="16dp"
android:background="#42d7f4"
android:padding="16dp">
<TextView
android:id="#+id/headerText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="FRUITS"
android:textSize="36sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/itemsList"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#9f41f2"
android:clickable="false"
android:focusable="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="#+id/clickView"
android:layout_width="0dp"
android:layout_height="0dp"
android:onClick="navigate"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:clickable="true"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
Now you can functionality perform through that view instead through ConstraintLayout.
Moreover, you look at this answer