When creating a popular fragment, I get an empty constructor error.
Please take a look at the code I wrote and how can I pass data when creating fragments?
mAdapter = SubPagerAdapter(childFragmentManager)
for (doc in it.docs!!) {
mAdapter.addFragment(
PopularFragment(doc.code, "#${doc.name}", 10),
doc.name
)
}
viewpager.adapter = mAdapter
tabs.setupWithViewPager(viewpager)
class PopularFragment(private val hashTagsCode: Int, private val title: String, private val ItemCount: Int) : Fragment() {
var mHashTagsCode = hashTagsCode
var mTitle = title
var mItemCount = ItemCount
}
You should always pass the data to Fragment using Bundle as arguments
class PopularFragment : Fragment() {
var mHashTagsCode = 0
lateinit var mTitle :String
var mItemCount = 0
companion object{
fun instance(hashTagsCode: Int, title: String, itemCount: Int){
val data = Bundle()
data.putString("hash_tag_codes", hashTagsCode)
data.putString("title", title)
data.putString("item_count", itemCount)
return PopularFragment().apply{
arguments = data
}
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
mItemCount = arguments?.getInt("item_count")?:0
mHashTagsCode = arguments?.getInt("hash_tag_codes")?:0
mTitle = arguments?.getString("title")
}
}
And for creating instance
mAdapter = SubPagerAdapter(childFragmentManager)
for (doc in it.docs!!) {
mAdapter
.addFragment(PopularFragment.intsance(doc.code, "#${doc.name}", 10),doc.name)
}
viewpager.adapter = mAdapter
tabs.setupWithViewPager(viewpager)
Related
i am just trying to code for Get API, but when i write some code for that. it seems error, i took a few hours but i not get the point, can you guys help me?
this is the Activity (ActivityQuran)
class CategoryQuran : AppCompatActivity() {
var mainAdapter: MainAdapter? = null
var mProgressBar: ProgressDialog? = null
var modelMain: MutableList<ModelMain> = ArrayList()
private lateinit var adapter: MainAdapter
private lateinit var postArrayList: ArrayList<MainAdapter>
private lateinit var progressDialog: ProgressDialog
private val TAG = "MAIN_TAG"
private var isSearch = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_detail_artikel)
//setup progress dialog
progressDialog = ProgressDialog (this)
progressDialog.setTitle("Mohon Tunggu")
mProgressBar = ProgressDialog(this)
mProgressBar!!.setTitle("Mohon Tunggu")
mProgressBar!!.setCancelable(false)
mProgressBar!!.setMessage("Sedang menampilkan data...")
llAbout.setOnClickListener {
startActivity(Intent(this#CategoryQuran, AboutActivity::class.java)) }
llPP.setOnClickListener {
startActivity(Intent(this#CategoryQuran, PrivacyPolicyActivity::class.java)) }
llDisclaimer.setOnClickListener {
startActivity(Intent(this#CategoryQuran, DisclaimerActivity::class.java)) }
rvListArticles.setHasFixedSize(true)
rvListArticles.setLayoutManager(LinearLayoutManager(this))
//get data
listArticle
//search
searchBtn.setOnClickListener {
}
}
private val listArticle: Unit
private get() {
mProgressBar!!.show()
AndroidNetworking.get(BloggerApi.ListPost)
.setPriority(Priority.MEDIUM)
.build()
.getAsJSONObject(object : JSONObjectRequestListener {
override fun onResponse(response: JSONObject) {
try {
mProgressBar!!.dismiss()
val playerArray = response.getJSONArray("items")
for (i in 0 until playerArray.length()) {
val jsonObject1 = playerArray.getJSONObject(i)
val dataApi = ModelMain()
dataApi.title = jsonObject1.getString("title")
dataApi.content = jsonObject1.getString("content")
dataApi.labels = jsonObject1.getString("labels")
dataApi.url = jsonObject1.getString("url")
val datePost = jsonObject1.getString("published")
val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
val outputFormat = SimpleDateFormat("dd-MM-yyyy")
val date = inputFormat.parse(datePost)
val datePostConvert = outputFormat.format(date)
dataApi.published = datePostConvert
val jsonObject2 = jsonObject1.getJSONObject("author")
val authorPost = jsonObject2.getString("displayName")
dataApi.author = authorPost
val jsonObject3 = jsonObject2.getJSONObject("image")
val authorImage = jsonObject3.getString("url")
dataApi.authorImage = Uri.parse("http:$authorImage").toString()
modelMain.add(dataApi)
showListArticle()
}
} catch (e: JSONException) {
e.printStackTrace()
Toast.makeText(this#CategoryQuran,
"Gagal menampilkan data!", Toast.LENGTH_SHORT).show()
} catch (e: ParseException) {
e.printStackTrace()
Toast.makeText(this#CategoryQuran,
"Gagal menampilkan data!", Toast.LENGTH_SHORT).show()
}
}
override fun onError(anError: ANError) {
mProgressBar!!.dismiss()
Toast.makeText(this#CategoryQuran,
"Tidak ada jaringan internet!", Toast.LENGTH_SHORT).show()
}
})
}
private fun showListArticle(){
mainAdapter = MainAdapter(this#CategoryQuran, modelMain, this )
rvListArticles!!.adapter = mainAdapter
}
private fun searchPosts(query: String) {
mainAdapter = MainAdapter(this#CategoryQuran, modelMain, this)
rvListArticles!!.adapter = mainAdapter
}
override fun onSelected(modelMain: ModelMain) {
val intent = Intent(this#CategoryQuran, DetailArtikelActivity::class.java)
intent.putExtra("detailArtikel", modelMain)
startActivity(intent)
}
}
i got error in 'this'
private fun showListArticle(){
mainAdapter = MainAdapter(this#CategoryQuran, modelMain, this )
rvListArticles!!.adapter = mainAdapter
}
private fun searchPosts(query: String) {
mainAdapter = MainAdapter(this#CategoryQuran, modelMain, this)
rvListArticles!!.adapter = mainAdapter
}
both show 'Type mismatch: inferred type is CategoryQuran but MainAdapter.onSelectData! was expected'
Can you guys help me? please
Ok so the problem is i am have to add OnSelectData in my Class, in my case what i have to do is add MainAdaper.OnSelectData
so Before it like :
class CategoryQuran : AppCompatActivity() {
and after it like :
class CategoryQuran : AppCompatActivity(), MainAdapter.OnSelectData {
thats my fault, im too rush when i coding it
After switching from removing kotlin_extensions and switching to view binding, I received a "Unresolved reference: myViewHolder" in my onBindViewHolder method and when I replace "myViewHolder" with "holder", it then gives me a "Unresolved reference: bind". How do I resolve this.
MyAdapter
class MyAdapter(private val context: Context, private val mHelper : TaskDbHelper) : RecyclerView.Adapter<MyAdapter.MyViewHolder>(),
SwipeAndDragHelper.ActionCompletionContract {
class MyViewHolder(val binding: CellCardsBinding): RecyclerView.ViewHolder(binding.root ) {
fun binding() {
}
}
private var touchHelper: ItemTouchHelper? = null
private var list = mutableListOf<MyObject>()
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
initList()
super.onAttachedToRecyclerView(recyclerView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(CellCardsBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
#RequiresApi(Build.VERSION_CODES.P)
#SuppressLint("ClickableViewAccessibility")
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val myObject = list[position]
myViewHolder.bind(myObject)
val activity: Activity = context as Activity
holder.binding.text.setOnClickListener{
activity.launchActivity<AddNoteActivity>(42) {
putExtra("PositionInList", position.toString())
putExtra("TaskTitle", myObject.title)
putExtra("TaskText", myObject.text)
}
}
activity.findViewById<RecyclerView>(R.id.recyclerView).setOnTouchListener { _, event ->
when (event.actionMasked) {
MotionEvent.ACTION_UP -> {
updateNotesPositionInDb()
false
}
else -> {
false
}
}
}
holder.binding.title.setOnTouchListener { _, event ->
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
touchHelper!!.startDrag(holder)
false
}
else -> {
false
}
}
}
}
private fun initList() {
list.clear()
val db = mHelper.readableDatabase
val cursor = db.query(
TaskContract.TaskEntry.TABLE,
arrayOf(
TaskContract.TaskEntry.ID,
TaskContract.TaskEntry.COL_TASK_TITLE,
TaskContract.TaskEntry.COL_TASK_TEXT,
TaskContract.TaskEntry.COL_TASK_DATE),null, null, null, null, TaskContract.TaskEntry.ID)
while (cursor.moveToNext()) {
val id = cursor.getColumnIndex(TaskContract.TaskEntry.ID)
val idTitle = cursor.getColumnIndex(TaskContract.TaskEntry.COL_TASK_TITLE)
val idText = cursor.getColumnIndex(TaskContract.TaskEntry.COL_TASK_TEXT)
val idDate = cursor.getColumnIndex(TaskContract.TaskEntry.COL_TASK_DATE)
list.add(MyObject(cursor.getString(id), cursor.getString(idTitle), cursor.getString(idText), cursor.getString(idDate)))
}
notifyDataSetChanged()
cursor.close()
db.close()
}
override fun getItemCount(): Int {
return list.size
}
override fun onViewMoved(oldPosition: Int, newPosition: Int) {
val target = list[oldPosition]
list.removeAt(oldPosition)
list.add(newPosition, target)
notifyItemMoved(oldPosition, newPosition)
}
override fun onViewSwiped(position: Int) {
deleteTask(list[position].ID)
list.removeAt(position)
notifyItemRemoved(position)
updateNotesPositionInDb()
}
fun setTouchHelper(touchHelper: ItemTouchHelper) {
this.touchHelper = touchHelper
}
fun addTask(taskTitle : String, taskText: String) {
val values = ContentValues()
val sdf = SimpleDateFormat("dd/MM/yyyy/", Locale.US)
val date = sdf.format(Date())
values.put(TaskContract.TaskEntry.ID, list.size)
values.put(TaskContract.TaskEntry.COL_TASK_TITLE, taskTitle)
values.put(TaskContract.TaskEntry.COL_TASK_TEXT, taskText)
values.put(TaskContract.TaskEntry.COL_TASK_DATE, date)
val db = mHelper.readableDatabase
db.insertWithOnConflict(TaskContract.TaskEntry.TABLE,
null,
values,
SQLiteDatabase.CONFLICT_REPLACE)
db.close()
list.add(MyObject(list.size.toString(), taskTitle, taskText, date))
notifyItemInserted(list.size)
}
fun addTask() {
val test: Activity = context as Activity
test.launchActivity<AddNoteActivity>(42) {
/* putExtra("user", "854")
p utExtra("user2", "46850") */
}
}
private fun deleteTask(taskId: String) {
val db = mHelper.readableDatabase
db.delete(TaskContract.TaskEntry.TABLE,
"id=$taskId", null)
db.close()
}
fun modifyTask(taskPosition: String, taskTitle: String, taskText: String) {
val target = list[taskPosition.toInt()]
target.title = taskTitle
target.text = taskText
val values = ContentValues()
val sdf = SimpleDateFormat("dd/MM/yyyy/", Locale.US)
val date = sdf.format(Date())
values.put(TaskContract.TaskEntry.ID, taskPosition)
values.put(TaskContract.TaskEntry.COL_TASK_TITLE, taskTitle)
values.put(TaskContract.TaskEntry.COL_TASK_TEXT, taskText)
values.put(TaskContract.TaskEntry.COL_TASK_DATE, date)
val db = mHelper.readableDatabase
db.update(TaskContract.TaskEntry.TABLE,
values, TaskContract.TaskEntry.ID + "=" + target.ID, null)
db.close()
notifyItemChanged(taskPosition.toInt())
}
private fun updateNotesPositionInDb() {
val db = mHelper.readableDatabase
var i = 0
while (i < list.size) {
val values = ContentValues()
values.put(TaskContract.TaskEntry.ID, i)
db.update(TaskContract.TaskEntry.TABLE,
values, TaskContract.TaskEntry.ID + "=? AND " + TaskContract.TaskEntry.COL_TASK_TITLE + "=?", arrayOf(list[i].ID, list[i].title))
i++
}
db.close()
}
I've tried reading Android Studio's official documentation, but it cannot solve my specific problem.
in your class MyViewHolder you have method called binding and you need also to implement it and add paramter
shoud be
class MyViewHolder(private val binding: CellCardsBinding): RecyclerView.ViewHolder(binding.root ) {
fun bind(data:MyObject) {
binding.yourView=data.title ...
}
}
in onBindViewHolder
..
holder.bind(myObject)
After switching from removing kotlin_extensions and switching to view binding, I received a "Unresolved reference: myViewHolder" in my onBindViewHolder method
Well, your onBindViewHolder method is passing a variable called holder and you're trying to use a variable called myViewHolder, so that seems like a problem.
// --------------------this-----v
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val myObject = list[position]
// v--- doesn't match this
myViewHolder.bind(myObject)
and when I replace "myViewHolder" with "holder", it then gives me a "Unresolved reference: bind". How do I resolve this.
Your MyViewHolder class has a method called binding that takes no arguments. There is no bind method that takes a "myObject".
class MyViewHolder(val binding: CellCardsBinding): RecyclerView.ViewHolder(binding.root ) {
fun binding() {
}
}
Edit
You should pass an instance of the data class
class MyViewHolder(val binding: CellCardsBinding): RecyclerView.ViewHolder(binding.root ) {
fun bind(object: MyObject) {
// Set variables on binding
}
}
Then pass an instance from your list via onBindViewHolder:
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val myObject = list[position]
holder.bind(myObject)
Please check this blog post for more.
I got my answer.
class MyAdapter(private val context: Context, private val mHelper : TaskDbHelper) : RecyclerView.Adapter<MyAdapter.MyViewHolder>(),
SwipeAndDragHelper.ActionCompletionContract {
class MyViewHolder(val binding: CellCardsBinding): RecyclerView.ViewHolder(binding.root ) {
private val titleView: TextView = itemView.findViewById<View>(R.id.title) as TextView
val textView: TextView = itemView.findViewById<View>(R.id.text) as TextView
private val dateTextView: TextView = itemView.findViewById<View>(R.id.date) as TextView
fun binding (myObject: MyObject) {
titleView.text = myObject.title
textView.text = myObject.text
dateTextView.text = myObject.date
}
}
I simply initialised the view I wanted to reference in my layout and called them in the binding() function.
I have 2 Recyclerviews in a fragment. Each item consists of 2 textview. When clicked, i want to change the color of item background and the 2 tvs and get the listofData(position) clicked also then send these s pieces of data to an activity.
The problem is 2 rvs each have its own adapter so i can't call the activity and check if data is selected from both adapters. And when i try it from the fragment i get the adapter position right but the view colors are not being changed correctly.
My RV element
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="2dp"
android:paddingBottom="10dp"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:background="#drawable/date_time_background"
android:elevation="0dp"
android:gravity="center"
android:layout_marginEnd="5dp"
android:orientation="vertical"
android:id="#+id/item_linear_layout">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/dateNameTV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Sat"
android:textColor="#color/black_65"
android:textSize="16sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/dateNumTV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="23/5"
android:textColor="#color/black_65"
android:textSize="16sp" />
</LinearLayout>
My RV adapter
class TimesAdapter(private var availableTimes: List<String>?, private val onTimeListener: OnTimeListener) :
RecyclerView.Adapter<TimesAdapter.TimeViewHolder>() {
private var itemIndex = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimeViewHolder {
val v = LayoutInflater.from(parent.context)
.inflate(R.layout.date_time_element, parent, false)
return TimeViewHolder(v, onTimeListener)
}
override fun getItemCount(): Int = availableTimes?.size!!
#SuppressLint("ClickableViewAccessibility")
override fun onBindViewHolder(holder: TimeViewHolder, position: Int) {
val currentDate: String? = availableTimes?.get(position) // i.e Sun 23/5
val parts = currentDate?.split(" ")
try {
val part1 = parts?.get(0)
holder.dateNameTV.text = part1
val part2 = parts?.get(1)
holder.dateNumTV.text = part2
} catch (e: IndexOutOfBoundsException) {
e.printStackTrace()
}
holder.itemLinearLayout.setOnClickListener {
itemIndex = position
notifyItemChanged(position)
}
val ctx = holder.itemLinearLayout.context
if (itemIndex == position) {
holder.itemLinearLayout.background = (loadDrawable(ctx, R.drawable.date_time_background_selected))
holder.dateNameTV.setTextColor(loadColor(ctx, android.R.color.white))
holder.dateNumTV.setTextColor(loadColor(ctx, android.R.color.white))
} else {
holder.itemLinearLayout.background = (loadDrawable(ctx, R.drawable.date_time_background))
holder.dateNameTV.setTextColor(loadColor(ctx, R.color.black_65))
holder.dateNumTV.setTextColor(loadColor(ctx, R.color.black_65))
}
}
class TimeViewHolder(itemView: View, onTimeListener: OnTimeListener) :
RecyclerView.ViewHolder(itemView), View.OnClickListener{
var dateNameTV: TextView = itemView.findViewById(R.id.dateNameTV)
var dateNumTV: TextView = itemView.findViewById(R.id.dateNumTV)
var itemLinearLayout: LinearLayout = itemView.findViewById(R.id.item_linear_layout)
private var onTimeListener: OnTimeListener? = null
init {
itemView.setOnClickListener(this)
this.onTimeListener = onTimeListener
}
override fun onClick(v: View?) {
onTimeListener?.onTimeClick(adapterPosition, itemView)
}
}
interface OnTimeListener{
fun onTimeClick(position: Int, itemView: View)
}
}
My fragment
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [DoctorAppointmentsFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class DoctorAppointmentsFragment : Fragment(),
DatesAdapter.OnDateListener, TimesAdapter.OnTimeListener {
private lateinit var datesRV: RecyclerView
private lateinit var timesRV: RecyclerView
private lateinit var linearLayoutManager: LinearLayoutManager
private lateinit var datesAdapter: DatesAdapter
private lateinit var timesAdapter: TimesAdapter
private lateinit var dateNameTV: TextView
private lateinit var dateNumTV: TextView
private lateinit var dateLinearLayout: LinearLayout
private var dates: List<String>? = null
private var times: List<String>? = null
private var isDateSelected = false
private var isTimeSelected = false
private var selectedDate: String? = null
private var selectedTime: String? = null
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_doctor_appointments, container, false)
datesRV = view.findViewById(R.id.datesRV)
datesRV.setHasFixedSize(true)
linearLayoutManager = LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
linearLayoutManager.isAutoMeasureEnabled = false
datesRV.layoutManager = linearLayoutManager
timesRV = view.findViewById(R.id.timesRV)
timesRV.setHasFixedSize(true)
linearLayoutManager = LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
linearLayoutManager.isAutoMeasureEnabled = false
timesRV.layoutManager = linearLayoutManager
val bookNowBT = view.findViewById<Button>(R.id.bookNowBT)
bookNowBT.setOnClickListener {
if (isDateSelected && isTimeSelected) {
val i = Intent(activity, ConfirmPaymentActivity::class.java)
i.putExtra(SELECTED_DATE, selectedDate)
i.putExtra(SELECTED_TIME, selectedTime)
startActivity(i)
}
}
getDoctorAvailableAppointments("7ab63fd2461bfb0008b72f5d8c0033fs", "basic")
return view
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment DoctorAppointmentsFragment.
*/
// TODO: Rename and change types and number of parameters
#JvmStatic
fun newInstance(param1: String, param2: String) =
DoctorAppointmentsFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
private fun getDoctorAvailableAppointments(doctorID: String, type: String) {
setProgressDialog(this.requireActivity())
if (!InternetConnection.isInternetAvailable(this.requireActivity())) {
alertError(this.requireActivity(),
R.string.no_internet_connection,
R.string.check_internet_connection)
} else {
showProgressDialog()
val builder = ServiceBuilder()
val appointments = builder.getDoctorAvailableReservations()
val call = appointments.getDoctorAvailableReservations(
RequestAvailableReservations(doctorID,type))
call?.enqueue(object : Callback<ResponseAvailableReservations?> {
override fun onResponse(call: Call<ResponseAvailableReservations?>, response: Response<ResponseAvailableReservations?>) {
dismissProgressDialog()
if (!response.isSuccessful) {
alertError(requireActivity(),
R.string.code_not_200,
R.string.try_later)
return
}
val body: ResponseAvailableReservations? = response.body()
if (body == null) {
alertError(requireActivity(),
R.string.null_body,
R.string.try_later)
return
}
val status = body.status
val message = body.message
val data = body.data
if (status == null || message == null || data == null) {
alertError(requireActivity(),
R.string.null_body,
R.string.try_later)
return
}
if (status == "error") {
alertError(requireActivity(), R.string.error, message)
} else if (status == "success") {
dates = data.availableDatesList
datesAdapter = DatesAdapter(dates, this#DoctorAppointmentsFragment)
datesRV.adapter = datesAdapter
times = data.availableTimesList
timesAdapter = TimesAdapter(times, this#DoctorAppointmentsFragment)
timesRV.adapter = timesAdapter
}
}
override fun onFailure(call: Call<ResponseAvailableReservations?>, t: Throwable) {
t.printStackTrace()
dismissProgressDialog()
alertError(requireActivity(),
R.string.fail,
R.string.login_fail)
}
})
}
}
private var dateIndex = -1
override fun onDateClick(position: Int) {
selectedDate = dates?.get(position)
isDateSelected = true
Log.e("selectedDate", "selectedDate")
dateIndex = position
datesAdapter.notifyDataSetChanged()
}
private var timeIndex = -1
override fun onTimeClick(position: Int, itemView: View) {
// selectedTime = times?.get(position)
// isTimeSelected = true
// Log.e("isSelectedTime", "true")
// timeIndex = position
// timesAdapter.notifyItemChanged(position)
// Log.e("timeIndex", timeIndex.toString())
//
// val ctx = itemView.context
// if (timeIndex == position) {
// Log.e("timeIndex", "timeIndex == position")
//
// itemView.background = loadDrawable(ctx, R.drawable.date_time_background_selected)
// itemView.dateNameTV?.setTextColor(loadColor(ctx, android.R.color.white))
// itemView.dateNumTV?.setTextColor(loadColor(ctx, android.R.color.white))
// } else {
// itemView.background = (loadDrawable(ctx, R.drawable.date_time_background))
// itemView.dateNameTV.setTextColor(loadColor(ctx, R.color.black_65))
// itemView.dateNumTV.setTextColor(loadColor(ctx, R.color.black_65))
// }
}
}
Solved
For anyone interested i ended up using a very simple idea. Instead of accessing the RecyclerView selected element from outside the adapter, i did all i wanted to do inside the adapter and used 4 static variables in the Fragment. 2 booleans to check
if date and time are selected or not and 2 Strings having the date and time actually selected.
Inside the Fragment:
companion object {
#JvmStatic var isTimeSelected = false
#JvmStatic var selectedTime = ""
#JvmStatic var isDateSelected = false
#JvmStatic var selectedDate = ""
....
}
Inside the Adapter's onBindViewHolder()
holder.itemLinearLayout.setOnClickListener {
selectedDate = dates?.get(position)!!
isDateSelected = true
listener?.onDateClick(position)
selectedIndex = position
notifyDataSetChanged()
}
val ctx = holder.itemLinearLayout.context
if (selectedIndex == position) {
holder.itemLinearLayout.background = (loadDrawable(ctx, R.drawable.date_time_background_selected))
holder.dateNameTV.setTextColor(loadColor(ctx, android.R.color.white))
holder.dateNumTV.setTextColor(loadColor(ctx, android.R.color.white))
} else {
holder.itemLinearLayout.background = (loadDrawable(ctx, R.drawable.date_time_background))
holder.dateNameTV.setTextColor(loadColor(ctx, R.color.black_65))
holder.dateNumTV.setTextColor(loadColor(ctx, R.color.black_65))
}
And i made sure static variables don't have old values using this
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
isTimeSelected = false
selectedTime = ""
isDateSelected = false
selectedDate = ""
}
I know it's bad practice to put onClickListener inside onBindViewHolder but i don't konw if the static variables thing is good or bad practice. Either way it's working fine for now.
There is many ways to do this, And I recommend the first one.
Using shared ViewModels for communication between fragments in the same activity. The idea is that you will tie up the ViewModel with activity and every fragment can access this ViewModel and in this ViewModel you will have a LiveData object that holds the data and observing it from both fragments and every change in the value of LiveData will affect each fragment. Shared ViewModel
Using interfaces for communication between fragments and it's a hard thing to do these days. Basic communication between fragments
Using EventBus it's easy but not recommended while you can use ViewModel at the first solution. EventBus
Try this
TimesAdapter
class TimesAdapter(
availableTimes: List<String>
) : RecyclerView.Adapter<TimesAdapter.TimeViewHolder>() {
var availableTimes:List<String> = availableTimes
set(value) {
field = value
notifyDataSetChanged()
}
var listener:TimeSelectedListener?=null
var selectedIndex:Int = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimeViewHolder {
return TimeViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.date_time_element, parent, false)
)
}
override fun getItemCount(): Int = availableTimes.count()
override fun onBindViewHolder(holder: TimeViewHolder, position: Int) {
val currentDate: String? = availableTimes[position] // i.e Sun 23/5
val parts = currentDate?.split(" ")
try {
val part1 = parts?.get(0)
val part2 = parts?.get(1)
holder.dateNameTV.text = part2
holder.dateNumTV.text = part1
} catch (e: IndexOutOfBoundsException) {
e.printStackTrace()
}
holder.itemLinearLayout.setOnClickListener {
listener?.onTimeClick(position)
selectedIndex = position
}
if (selectedIndex == position) {
// Selection Code
} else {
// De selection code
}
}
class TimeViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var dateNameTV: TextView = itemView.findViewById(R.id.dateNameTV)
var dateNumTV: TextView = itemView.findViewById(R.id.dateNumTV)
var itemLinearLayout: LinearLayout = itemView.findViewById(R.id.item_linear_layout)
}
interface TimeSelectedListener {
fun onTimeClick(position: Int)
}
}
Usage from fragment
times = data.availableTimesList
timesAdapter = TimesAdapter(times).apply {
listener = object :TimesAdapter.TimeSelectedListener{
override fun onTimeClick(position: Int) {
// TODO here is where you should implement when an item is selected
}
}
}
timesRV.adapter = timesAdapter
I have recently developed android app using Kotlin but I am getting the following error
Cannot infer a type for this parameter. Please specify it explicitly
below screenshot of the error
below my class where I am getting error
class AddBookingActivity : AppCompatActivity() {
#BindView(R.id.attendees_recycler_view)
internal var mAttendeeRecyclerView: RecyclerView? = null
#BindView(R.id.start_time_edit_text)
internal var mStartTime: EditText? = null
#BindView(R.id.end_time_edit_text)
internal var mEndTime: EditText? = null
private var mAttendeeName: EditText? = null
private var mAttendeeEmail: EditText? = null
private var mAttendeePhoneNumber: EditText? = null
private var mAttendeeAdapter: AttendeeAdapter? = null
private var mAlertDialog: AlertDialog? = null
private val mAttendeeItemList = ArrayList<AttendeeItem>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_booking)
ButterKnife.bind(this)
mAttendeeRecyclerView!!.layoutManager = LinearLayoutManager(this)
mAttendeeAdapter = AttendeeAdapter(this)
mAttendeeAdapter!!.setAttendeeList(mAttendeeItemList)
mAttendeeRecyclerView!!.adapter = mAttendeeAdapter
}
#OnClick(R.id.toolbar_back_button)
internal fun onBackButtonClicked() {
onBackPressed()
}
#OnClick(R.id.start_time_edit_text)
internal fun onStartTimeClicked() {
showTimePickerDialog(mStartTime)
}
#OnClick(R.id.end_time_edit_text)
internal fun onEndTimeClicked() {
showTimePickerDialog(mEndTime)
}
#OnClick(R.id.fab_add_attendee)
internal fun onAddAttendeeClicked() {
val inflater = this.layoutInflater
val dialogView = inflater.inflate(R.layout.add_attendee_view, null)
mAttendeeName = dialogView.findViewById(R.id.attendee_name)
mAttendeeEmail = dialogView.findViewById(R.id.attendee_email)
mAttendeePhoneNumber = dialogView.findViewById(R.id.attendee_phone_number)
mAlertDialog = AlertDialog.Builder(this, R.style.AlertDialog)
.setTitle("Input attendee details")
.setPositiveButton("Add") { dialog, which ->
val item = AttendeeItem()
item.name = mAttendeeName!!.text.toString()
item.email = mAttendeeEmail!!.text.toString()
item.phoneNumber = mAttendeePhoneNumber!!.text.toString()
mAttendeeItemList.add(item)
mAttendeeAdapter!!.setAttendeeList(mAttendeeItemList)
mAttendeeAdapter!!.notifyItemInserted(mAttendeeItemList.size)
}
.setNegativeButton("Cancel", null)
.setView(dialogView).create()
mAlertDialog!!.show()
}
private fun showTimePickerDialog(editText: EditText?) {
val myCalender = Calendar.getInstance()
val hour = myCalender.get(Calendar.HOUR_OF_DAY)
val minute = myCalender.get(Calendar.MINUTE)
#SuppressLint("DefaultLocale")
val myTimeListener = { view, hourOfDay, minute1 ->
if (view.isShown()) {
myCalender.set(Calendar.HOUR_OF_DAY, hourOfDay)
myCalender.set(Calendar.MINUTE, minute1)
editText!!.setText(String.format(String.format("%s:%s", hourOfDay.toString(), minute1.toString())))
}
}
val timePickerDialog = TimePickerDialog(this, android.R.style.Theme_Holo_Light_Dialog_NoActionBar, myTimeListener, hour, minute, true)
timePickerDialog.setTitle("Choose hour:")
timePickerDialog.window!!.setBackgroundDrawableResource(android.R.color.transparent)
timePickerDialog.show()
}
}
You have to specify the interface to help Kotlin compiler:
#SuppressLint("DefaultLocale")
val myTimeListener = TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute1 ->
if (view.isShown()) {
myCalender.set(Calendar.HOUR_OF_DAY, hourOfDay)
myCalender.set(Calendar.MINUTE, minute1)
editText!!.setText(String.format(String.format("%s:%s", hourOfDay.toString(), minute1.toString())))
}
}
how to put this ArrayList in this method?
Could someone tell me how to pass this ArrayList in this method?
I added all the fragment code could anyone guide me?
I tried in several ways to pass this ArrayList but without success always remains blank the fragment
thanks
Array List
<string-array name="object_types">
method
private var issues: ArrayList<Issue> = ArrayList()
private fun getIssues() {
val stream = resources.openRawResource(R.raw.markers)
val inputString = stream.bufferedReader().use {
it.readText()
}
val klaxon = Klaxon()
JsonReader(StringReader(inputString)).use { reader -> // requires kotlin > 1.2 !!
reader.beginArray {
while (reader.hasNext()) { // requires "[]" array and not {"something": []}
val issue = klaxon.parse<Issue>(reader)
this.issues!!.add(issue!!)
} }
}
this.issues = Utils.markers
}
GalleryFragment
all fragment code follows below
class GalleryFragment : Fragment(), IssueItemOnClickListener {
private var productsRecyclerView: RecyclerView? = null
private var recyclerAdapter: IssueRecyclerViewAdapter? = null
private var recyclerLayoutManager: RecyclerView.LayoutManager? = null
private var issues: ArrayList<Issue> = ArrayList()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_gallery, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
getIssues()
this.productsRecyclerView = view.findViewById(R.id.issue_list_recycler_view) as RecyclerView
this.productsRecyclerView!!.setHasFixedSize(true)
// use a grid layout manager -> 2 columns
this.recyclerLayoutManager = GridLayoutManager(context, 2) as RecyclerView.LayoutManager?
this.productsRecyclerView!!.layoutManager = this.recyclerLayoutManager
this.recyclerAdapter = IssueRecyclerViewAdapter(this.issues, this)
this.productsRecyclerView!!.adapter = recyclerAdapter
}
override fun onIssueItemClick(pos: Int, issue: Issue) {
val args = Bundle()
val detailsFragment = IssueDetailsFragment()
args.putDouble("lat", issue.lat)
args.putDouble("lng", issue.lng)
args.putString("description", issue.description)
args.putString("name", issue.name)
args.putString("type", issue.type)
args.putString("imgUrl", issue.imgUrl)
detailsFragment.arguments = args
val ft = activity!!.supportFragmentManager.beginTransaction()
ft.replace(R.id.main_fragment_content, detailsFragment)
.setTransition(android.app.FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.addToBackStack(null).commit()
}
private fun getIssues() {
val stream = resources.openRawResource(R.raw.markers)
val inputString = stream.bufferedReader().use {
it.readText()
}
val klaxon = Klaxon()
JsonReader(StringReader(inputString)).use { reader -> // requires kotlin > 1.2 !!
reader.beginArray {
while (reader.hasNext()) { // requires "[]" array and not {"something": []}
val issue = klaxon.parse<Issue>(reader)
this.issues!!.add(issue!!)
}
}
}
this.issues = Utils.markers
}
}
[SOLVED]
CHANGE
private var issues: ArrayList<Issue> = ArrayList()
TO
private var object_values: ArrayList<Issue> = ArrayList()