Fragment to Fragment transaction in Adapter Class Android - android

Hello I'm new in Android Developing and I'm creating a family Application in Android Studio. Whenever I want to go to another fragment in Adapter class the fragment is overlapping old fragment.
I want to go to Another fragment name SubFamilyFragment() from the adapter class.
I tried many ways from internet but I'm not getting success.
Here is my Adapter class code
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import com.example.mks.Fragments.SubFamilyFragment
import com.example.mks.Models.Family
import com.example.mks.R
class FamilyRecyclerAdapter(val context: Context, val familyList: ArrayList<Family>) : RecyclerView.Adapter<FamilyRecyclerAdapter.viewHolder>() {
class viewHolder(view: View) : RecyclerView.ViewHolder(view) {
val familyName : TextView = view.findViewById(R.id.familyName)
val familyMember : TextView = view.findViewById(R.id.familyMemberCount)
val subFamily : CheckBox = view.findViewById(R.id.chkSubFamily)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): viewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.family_recycler_single_row,parent,false)
return viewHolder(view)
}
override fun getItemCount(): Int {
return familyList.size
}
override fun onBindViewHolder(holder: viewHolder, position: Int) {
val number = familyList[position]
holder.familyName.text = number.familyName
holder.familyMember.text = number.familyMember.toString()
holder.subFamily.text = number.subFamily.toString()
holder.itemView.setOnClickListener {
val activity : AppCompatActivity = it.context as AppCompatActivity
if (number.subFamily){
// val fragment2 = SubFamilyFragment()
// val fragmentTransaction: FragmentTransaction = activity.supportFragmentManager.beginTransaction()
// fragmentTransaction.replace(R.id.nav_host_fragment, fragment2)
// fragmentTransaction.commit()
val myFragment: Fragment = SubFamilyFragment()
(it.getContext() as AppCompatActivity).supportFragmentManager.beginTransaction()
.replace(R.id.nav_host_fragment, myFragment).addToBackStack(null)
.commit()
}
else{
Toast.makeText(context,"No Sub Family",Toast.LENGTH_SHORT).show()
}
}
}
}```
This code is working but the fragment is overlapping.
Please tell me what to do.

Related

Firebase remove child recyclerview Kotlin

I need to remove child from Firebase after onClick from RecyclerView Adapter.
I have something like this:
Firebase database is
recyclerview is
My biggest problem is not sure how to get the "key" of the child node from the recyclerview.
I have been stuck on this supposedly simple thing for about 3 days so hopefully any help is appreciated.
package com.cpg12.findingfresh.adapters
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.cpg12.findingfresh.R
import com.cpg12.findingfresh.database.ShoppingList
import com.google.firebase.database.FirebaseDatabase
class ShoppingListAdapter : RecyclerView.Adapter<ShoppingListAdapter.ShoppingListViewHolder>() {
private val shoppingList = ArrayList<ShoppingList>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShoppingListViewHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.shopping_list_item, parent, false)
/** References the node to which market data is stored**/
val databaseReference = FirebaseDatabase.getInstance().getReference("Users")
return ShoppingListViewHolder(itemView)
}
override fun onBindViewHolder(holder: ShoppingListAdapter.ShoppingListViewHolder, position: Int) {
val currentItem = shoppingList[position]
holder.sListItem.text = currentItem.shoppingItem
}
override fun getItemCount(): Int {
return shoppingList.size
}
fun updateShoppinglist(shoppingList: List<ShoppingList>){
this.shoppingList.clear()
this.shoppingList.addAll(shoppingList)
notifyDataSetChanged()
}
class ShoppingListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
val sListItem : TextView = itemView.findViewById(R.id.ShoppingItemTV)
override fun onClick(v: View?) {
databaseReference.child(marketName).setValue(markets).child(key).setValue("")
}
}
}

context as a parameter takes this in android and allow us to implement method of interface. Why so?

My Main Activity Class
This is implemented to learn recycler view and to handle clicks. The below code works fine but while implementing listener I got confused. All the doubts are listed below. Do help.
package com.suasnom.pizzarecyclerview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity(), isClickedInterface {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//implementing recycler view
recycler_view.layoutManager= LinearLayoutManager(this)
val data = fetchData()
val adapter = CustomAdapter(data, this)
recycler_view.adapter = adapter
}
fun fetchData(): ArrayList<String> {
val list_Strings = ArrayList<String>()
var str = ""
for(i in 1..100){
str = "${i} line"
list_Strings.add(str)
}
return list_Strings
}
override fun onItemClicked(item: String) {
Toast.makeText(this, "$item", Toast.LENGTH_LONG).show()
}
}
In this statement I passed
val adapter = CustomAdapter(data, this)
and it allows me to override the below method:
override fun onItemClicked(item: String) {
Toast.makeText(this, "$item", Toast.LENGTH_LONG).show()
}
The below code is for recycler view adapter where I write that interface:
package com.suasnom.pizzarecyclerview
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class CustomAdapter(val list_strings: ArrayList<String>, private val listner: isClickedInterface): RecyclerView.Adapter<PizzaViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PizzaViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.row, parent, false)
val pizzaObject = PizzaViewHolder(view)
view.setOnClickListener {
listner.onItemClicked(list_strings[pizzaObject.adapterPosition])
}
return pizzaObject
}
override fun onBindViewHolder(holder: PizzaViewHolder, position: Int) {
val data_incoming = list_strings[position]
holder.text_message.text = data_incoming
}
override fun getItemCount(): Int {
return list_strings.size
}
}
class PizzaViewHolder(private val view: View): RecyclerView.ViewHolder(view){
val text_message = view.findViewById<TextView>(R.id.textrow)
}
interface isClickedInterface{
fun onItemClicked(item: String){}
}
Any idea how this is working. Please Help ...
inside CustomAdapter on the bottom you have declared isClickedInterface (it might be declared anywhere else or as separated file). it is implemented by your MainActivity (after :), so you have to set this interface methods inside implementing class - so in Activity appears onItemClicked(item: String) method
now your CustomAdapter have constructor param to pass this interface (second one). for initiating new instance of adapter you have pass implemented interface, in here you may pass whole Activity as it implements desired interface (val adapter = CustomAdapter(data, this) - this points on Activity, which is also an isClickedInterface interface instance)
now inside onCreateViewHolder you are setting setOnClickListener and inside of it you are calling method from passed interface in constructor

The recycler view in my fragment is causing the animations to look choppy

My app is a dictionary app. I am using a room database to save the recent queries in my app. I am showing all the contents of the room database inside my recycler view. When the user searches for a word, the user is taken to the result fragment and the query is added to the room database behind the scenes. It also plays a slide in from right animation when the new fragment is getting added. On pressing the back or the up button, it should take you back with an animation the top level fragment, the main fragment. But the problem I am facing is that something with the recycler view makes that animation look very choppy.
This is how it should look: https://i.imgur.com/vdOtA2Y.mp4
This is how it looks: https://i.imgur.com/OKpDj7G.mp4
I am pasting the fragment with the recycler view, viewmodel and the recycler view adapter here and I am also pasting a link to the whole app's github repo https://github.com/sbeve72/JADA
package com.sbeve.jada.fragments.main
import android.os.Bundle
import android.view.View
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.sbeve.jada.R
import com.sbeve.jada.activities.MainActivity
import com.sbeve.jada.databinding.FragmentMainBinding
import com.sbeve.jada.recyclerview_utils.RecentQueriesAdapter
import com.sbeve.jada.retrofit_utils.RetrofitInit
class MainFragment : Fragment(R.layout.fragment_main), RecentQueriesAdapter.OnItemClickListener {
private val navController: NavController by lazy {
this.findNavController()
}
//the currently running instance of the activity
private val mainActivityContext: MainActivity by lazy {
activity as MainActivity
}
private val stayInPlaceAnimation: Animation? by lazy {
val anim: Animation = AlphaAnimation(1.0F, 1.0F)
anim.duration = 150
anim
}
private val viewModel: MainViewModel by viewModels()
private lateinit var fragmentMainBinding: FragmentMainBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
fragmentMainBinding = FragmentMainBinding.bind(view)
fragmentMainBinding.queriesRecyclerView.layoutManager = LinearLayoutManager(mainActivityContext)
fragmentMainBinding.currentLanguage.text = RetrofitInit.supportedLanguages.first[mainActivityContext.savedLanguageIndex]
fragmentMainBinding.changeLanguageGearIcon.setOnClickListener {
createChangeLanguageDialog().show()
}
fragmentMainBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
//work
viewModel.addQuery(mainActivityContext.savedLanguageIndex, query)
navController.navigate(MainFragmentDirections.actionMainFragmentToResultFragment(query))
hideSoftKeyboard()
return true
}
override fun onQueryTextChange(newText: String?) = false
})
setAdapter()
}
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int) = stayInPlaceAnimation
private fun createChangeLanguageDialog() =
MaterialAlertDialogBuilder(mainActivityContext)
.setTitle(getString(R.string.choose_a_language))
.setSingleChoiceItems(RetrofitInit.supportedLanguages.first, mainActivityContext.savedLanguageIndex)
{ dialogInterface, i ->
fragmentMainBinding.currentLanguage.text = RetrofitInit.supportedLanguages.first[i]
mainActivityContext.applicationSharedPreferences
.edit()
.putInt(getString(R.string.language_setting_key), i)
.apply()
dialogInterface.dismiss()
}
.create()
//hides the keyboard
private fun hideSoftKeyboard() {
val imm: InputMethodManager = mainActivityContext.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
//Find the currently focused view, so we can grab the correct window token from it.
var view = mainActivityContext.currentFocus
//If no view currently has focus, create a new one, just so we can grab a window token from it
if (view == null) {
view = View(activity)
}
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
private fun setAdapter() {
viewModel.allQueries.observe(viewLifecycleOwner) {
val adapter = RecentQueriesAdapter(it, this)
fragmentMainBinding.queriesRecyclerView.adapter = adapter
}
}
override fun onItemClick(position: Int) {
val queryText = viewModel.allQueries.value!![position].queryText
navController.navigate(MainFragmentDirections.actionMainFragmentToResultFragment(queryText))
}
}
package com.sbeve.jada.fragments.main
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sbeve.jada.myApplication
import com.sbeve.jada.retrofit_utils.RetrofitInit
import com.sbeve.jada.room_utils.DictionaryDatabase
import com.sbeve.jada.room_utils.DictionaryDatabaseDAO
import com.sbeve.jada.room_utils.RecentQuery
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MainViewModel : ViewModel() {
private var roomDatabase = DictionaryDatabase.getInstance(myApplication.getInstance())
private val databaseDao: DictionaryDatabaseDAO = roomDatabase.getDao()
val allQueries = databaseDao.getAllQueries()
fun addQuery(languageIndex: Int, query: String) {
viewModelScope.launch {
withContext(IO) {
val recentQuery = RecentQuery(0, query, RetrofitInit.supportedLanguages.first[languageIndex], System.currentTimeMillis())
databaseDao.addQuery(recentQuery)
}
}
}
}
package com.sbeve.jada.recyclerview_utils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.text.HtmlCompat
import androidx.recyclerview.widget.RecyclerView
import com.sbeve.jada.databinding.QueryLayoutBinding
import com.sbeve.jada.room_utils.RecentQuery
import java.text.SimpleDateFormat
import java.util.*
class RecentQueriesAdapter(private val dataSet: List<RecentQuery>, private val onItemClickListener: OnItemClickListener) :
RecyclerView.Adapter<RecentQueriesAdapter.ViewHolder>() {
class ViewHolder(myItemView: QueryLayoutBinding, private val onItemClickListener: OnItemClickListener) :
RecyclerView.ViewHolder(myItemView.root), View.OnClickListener {
init {
myItemView.root.setOnClickListener(this)
}
private val queryText = myItemView.queryText
fun setQueryText(queryValue: String) {
queryText.text = HtmlCompat.fromHtml(queryValue, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
private val time = myItemView.time
fun setTimeText(timeValue: Long) {
time.text = SimpleDateFormat.getDateTimeInstance().format(Date(timeValue))
}
override fun onClick(v: View?) {
onItemClickListener.onItemClick(adapterPosition)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = QueryLayoutBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding, onItemClickListener)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val currentItem = dataSet[position]
holder.setQueryText(currentItem.queryText)
holder.setTimeText(currentItem.timeDate)
}
override fun getItemCount() = dataSet.size
interface OnItemClickListener {
fun onItemClick(position: Int)
}
}

Implicit Intent is not working due to context issue

Here is my code :-
Favourite Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import java.security.AccessController.getContext
//this is my calling activity
class FavouriteActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.favourite_activity)
val mToolbar: Toolbar = findViewById(R.id.toolbar_favourite)
setSupportActionBar(mToolbar)
getSupportActionBar()?.setDisplayHomeAsUpEnabled(true);
getSupportActionBar()?.setDisplayShowHomeEnabled(true);
setTitle("Favourite Activity");
//getting recyclerview from xml
val recyclerView = findViewById(R.id.recyclerView) as RecyclerView
//adding a layoutmanager
recyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
//it can be staggered and grid
//creating our adapter
val adapter = CustomAdapter(star) //here I am calling the adapter activity
//now adding the adapter to recyclerview
recyclerView.adapter = adapter
}
override fun onSupportNavigateUp(): Boolean {
onBackPressed()
return true
}
}
CustomAdapter class
class CustomAdapter(val userList: ArrayList<User>) : RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
//this method is returning the view for each item in the list
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.list_layout_favourite, parent, false)
return ViewHolder(v)
}
//this method is binding the data on the list
override fun onBindViewHolder(holder: CustomAdapter.ViewHolder, position: Int) {
holder.bindItems(userList[position])
holder.imgCopy.setOnClickListener(View.OnClickListener {
holder.shareString(userList[position])
Toast.makeText(holder.itemView.getContext(),"Copy Button Clicked", Toast.LENGTH_SHORT).show()
})
}
//this method is giving the size of the list
override fun getItemCount(): Int {
return userList.size
}
//the class is holding the list view
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imgCopy: ImageView = itemView.findViewById(R.id.img_copy) as ImageView
val textViewName = itemView.findViewById(R.id.tvTitle) as TextView
fun bindItems(user: User) {
textViewName.text = user.name
}
fun shareString(user: User)
{
val message : String = user.name
val intent = Intent()
intent.action = Intent.ACTION_SEND
intent.putExtra(Intent.EXTRA_TEXT,message)
intent.type = "text/plain"
startActivity(Intent.createChooser(intent,"Share to :")) ///Issue occur right here
}}}
Getting error : Required context , found Intent.
it is working fine in other FragmentActivity.
I have tried various methods to called the context. but anything is not working.
I have also passed the context from Fragment activity, but that also not worked.
Please let me know is there any way to start Intent.
As I am always getting error and stuck due to this.
The startActivity available in the ViewHolder class is different from the one available in activites. So in this method (available in viewholder), the first parameter should be a context. So pass the context as follows:
startActivity(itemView.context, Intent.createChooser(intent,"Share to :"))

Can not import Adapter

Im learning Kotlin and Mvvm for Android. I am using a recycler view, and when i try to set the adapter i cant import the Adapter class, I dont know if the problem is in the code because Android Studio let me import ViewHolder class inside the Adapter class but not Adapter class
FrontPageActivity.kt
package com.jmyp.resport.view
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.jmyp.resport.model.New
import com.jmyp.resport.R
import com.jmyp.resport.viewmodel.NewViewModel
class FrontPageActivity : AppCompatActivity() {
lateinit var adapter : NewsAdapter // I can not import this but i can
// NewsAdapter.NewViewHolder
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_front_page)
var viewModelNews = ViewModelProviders.of(this).get(NewViewModel::class.java)
viewModelNews.getNews().observe(this, Observer<ArrayList<New>> { news ->
adapter = NewsAdapter(this, news)
})
}
}
NewsAdapter.kt
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.jmyp.resport.model.New
import com.jmyp.resport.R
import com.jmyp.resport.view.FrontPageActivity
import kotlinx.android.synthetic.main.row_front_page.view.*
class NewsAdapter(private val context: FrontPageActivity, private val news : ArrayList<New>) : RecyclerView.Adapter<NewsAdapter.NewViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewViewHolder {
return NewViewHolder(LayoutInflater.from(context).inflate(R.layout.row_front_page,parent,false))
}
override fun getItemCount(): Int {
return news.size
}
override fun onBindViewHolder(holder: NewViewHolder, position: Int) {
holder.title.text = news.get(position).titulo
}
class NewViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val cover = itemView.iv_cover
val title = itemView.tv_title
}
}
You seem to be missing package in your Adapter class. Add it and try again :)

Categories

Resources