Im trying to proceed on the next activty from Kotlin to Java it gives me a red line in ".java"
in
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
This is my whole code:
package com.heyletscode.artutorial
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
class Garlic : AppCompatActivity() {
lateinit var button : Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_garlic)
button = findViewById(R.id.Button)
button.setOnClickListener(listener)
}
val listener= View.OnClickListener { view ->
when (view.getId()) {
R.id.Button -> {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
}
}
}
Ive tried different methods to proceed to next activty but give me red line in .java
I'd suggest moving your listener set-up to your onCreate like this
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_garlic)
button = findViewById(R.id.Button)
button.setOnClickListener { ->
val intent = Intent(this#Garlic, MainActivity::class.java)
startActivity(intent)
}
}
and the this is referencing to your onClickListener, append it with # followed by your activity name
val intent = Intent(this#Garlic, MainActivity::class.java)
may be you provide wrong context to Intent try below code
package com.heyletscode.artutorial
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
class Garlic : AppCompatActivity() {
lateinit var button : Button
private lateinit var context: Context //create object of context
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_garlic)
context= this#MainActivity // init context here
button = findViewById(R.id.Button)
button.setOnClickListener(listener)
}
val listener= View.OnClickListener { view ->
when (view.getId()) {
R.id.Button -> {
val intent = Intent(context, MainActivity::class.java) //replace this with context
startActivity(intent)
}
}
}
}
Related
Trying to add an onclicklistener to the items in my recycler view, that will use an intent to open another activity. I've tried finding examples, but I can only find examples using Java or Kotlin examples that aren't using viewbinding.
package com.truuce.anotherrvtest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.GridLayoutManager
import com.truuce.anotherrvtest.databinding.ActivityHeroBinding
class HeroActivity : AppCompatActivity() {
var binding: ActivityHeroBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHeroBinding.inflate(layoutInflater)
setContentView(binding?.root)
val adapter = CardAdapter(HeroList.heroList)
binding?.heroRV?.adapter = adapter
binding?.heroRV?.layoutManager = GridLayoutManager(applicationContext, 3)
}
override fun onDestroy() {
super.onDestroy()
binding = null
}
}
package com.truuce.anotherrvtest
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.truuce.anotherrvtest.databinding.HeroCardBinding
class CardAdapter(val heroList: List<Hero>) : RecyclerView.Adapter<CardAdapter.MainViewHolder>() {
inner class MainViewHolder(val heroBinding: HeroCardBinding) :
RecyclerView.ViewHolder(heroBinding.root) {
fun bindHero(hero: Hero){
heroBinding.heroNameTV.text = hero.heroName
heroBinding.heroIV.setImageResource(hero.image)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainViewHolder {
return MainViewHolder(HeroCardBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
override fun onBindViewHolder(holder: MainViewHolder, position: Int) {
val hero = heroList[position]
holder.bindHero(hero)
}
override fun getItemCount() = heroList.size
}
tried adding View.OnClickListener to MainViewHolder, then implemented a member. OnClick(p0: View){}, but no idea how to get it working.
You should add a functional property for a click listener in your adapter.
The Activity can set the item click listener behavior.
class CardAdapter(
val heroList: List<Hero>,
val itemClickListener: (Hero)->Unit
) : RecyclerView.Adapter<CardAdapter.MainViewHolder>() {
inner class MainViewHolder(val heroBinding: HeroCardBinding) :
RecyclerView.ViewHolder(heroBinding.root) {
fun bindHero(hero: Hero) = with(heroBinding) {
heroNameTV.text = hero.heroName
heroIV.setImageResource(hero.image)
root.setOnClickListener { itemClickListener(hero) }
}
}
//...
}
// In Activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHeroBinding.inflate(layoutInflater)
setContentView(binding?.root)
val adapter = CardAdapter(HeroList.heroList) { hero ->
// do something with hero item when it's clicked
}
binding?.heroRV?.adapter = adapter
binding?.heroRV?.layoutManager = GridLayoutManager(applicationContext, 3)
}
I'm struggling with both a dilemma and an issue here. The dilemma is that I want to keep the ManagerUsers screen simple, but Google is pushing fragments. I can see a use for fragments for this screen later on, but for now, it seems like overkill. Should I use them anyway?
Second, if I do avoid fragments for now, I am struggling to finish setting up the ClickListener to simply change the name of the user in the ListView. Kotlin seems to have at least 6 different methods for doing most things, making it confusing to figure this out. Google's tutorials force you to use fragments, and others' tutorials don't really cover what I'm trying to do. When I navigate to the Manage Users activity, the app crashes. LogCat shows that userSelect needs to be initialized. I have no idea how to do that.
UserListAdapter.kt
package com.neillbarrett.debitsandcredits
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.neillbarrett.debitsandcredits.database.UsersTable
import com.neillbarrett.debitsandcredits.databinding.ActivityManageUsersBinding
class UserListAdapter(private val userSelect: (UsersTable?) -> Unit) :
ListAdapter<UsersTable, UserListAdapter.UserViewHolder>(UsersComparator()) {
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
val current = getItem(position)
holder.bind(current, userSelect)
}
class UserViewHolder(private val binding: ActivityManageUsersBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(usersTable: UsersTable?, userSelect: (UsersTable?) -> Unit) {
binding.root.setOnClickListener( View.OnClickListener {
userSelect(usersTable)
binding.etEditName.setText(R.layout.activity_list_of_users.toString())
})
}
companion object {
fun create(parent: ViewGroup) : UserViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.activity_manage_users, parent, false)
return UserViewHolder(ActivityManageUsersBinding.bind(view))
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.activity_manage_users, parent, false)
return UserViewHolder.create(parent)
}
class UsersComparator : DiffUtil.ItemCallback<UsersTable>() {
override fun areItemsTheSame(oldItem: UsersTable, newItem: UsersTable): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: UsersTable, newItem: UsersTable): Boolean {
return oldItem.userName == newItem.userName
}
}
}
ManageUsers.kt
package com.neillbarrett.debitsandcredits
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.neillbarrett.debitsandcredits.database.CreditsAndDebitsApp
import com.neillbarrett.debitsandcredits.database.UsersTable
import com.neillbarrett.debitsandcredits.databinding.ActivityManageUsersBinding
class ManageUsers : AppCompatActivity() {
lateinit var binding: ActivityManageUsersBinding
lateinit var recyclerView: RecyclerView
lateinit var editTextAddUser: EditText
lateinit var editTextChangeUser: EditText
lateinit var newUser: String
lateinit var userSelect: ((UsersTable?) -> Unit)
var position: Long = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityManageUsersBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
//setContentView(R.layout.activity_manage_users)
val userViewModel: UserViewModel by viewModels {
UserViewModelFactory((application as CreditsAndDebitsApp).repository)
}
recyclerView = findViewById(R.id.rec_view_userList)
editTextAddUser = findViewById(R.id.et_UserName)
editTextChangeUser = findViewById(R.id.et_Edit_Name)
val adapter = UserListAdapter(userSelect)
binding.recViewUserList.adapter = adapter
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
userViewModel.allUsers.observe(this, Observer() {user ->
user?.let { adapter.submitList(it) }
})
val btnAddUser = findViewById<Button>(R.id.btn_AddUser)
btnAddUser.setOnClickListener {
if (TextUtils.isEmpty(editTextAddUser.text)) {
Toast.makeText(this, "User name cannot be empty", Toast.LENGTH_SHORT).show()
} else {
newUser = editTextAddUser.text.toString()
userViewModel.insertUser(UsersTable(0, newUser))
}
}
val btnChangeUser = findViewById<Button>(R.id.btn_ChangeUserName)
btnChangeUser.setOnClickListener {
if (recyclerView.getChildAdapterPosition(it) == -1) {
Toast.makeText(this, "Select a name.", Toast.LENGTH_SHORT).show()
} else {
if (editTextChangeUser.text.toString() == recyclerView.adapter.toString()) {
Toast.makeText(this, "Name has not been changed.", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Name would have been changed.", Toast.LENGTH_SHORT).show()
/*val rvItemRecId: Long
rvItemRecId = adapter.getItemId(position.toInt())
userViewModel.updateUser(UsersTable(rvItemRecId.toInt(), adapter.toString()))*/
}
}
}
}
}
UserViewModel.kt
package com.neillbarrett.debitsandcredits
import androidx.lifecycle.*
import com.neillbarrett.debitsandcredits.database.UsersTable
import kotlinx.coroutines.launch
import java.lang.IllegalArgumentException
class UserViewModel(private val repository: UserRepository) : ViewModel() {
val allUsers: LiveData<List<UsersTable>> = repository.allUsers.asLiveData()
fun insertUser(user: UsersTable) = viewModelScope.launch {
repository.insertUser(user)
}
fun updateUser(user: UsersTable) = viewModelScope.launch {
repository.updateUser(user)
}
fun deleteUser(user: UsersTable) = viewModelScope.launch {
repository.deleteUser(user)
}
}
class UserViewModelFactory(private val repository: UserRepository) : ViewModelProvider.Factory{
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(UserViewModel::class.java)) {
#Suppress("UNCHECKED_CAST")
return UserViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
If you check your ManageUsers activity implementation
lateinit var userSelect: ((UsersTable?) -> Unit)
userSelect is lateinit and it must be initialised before you pass the reference to UserListAdapter adapter. Something like this
userSelect = {
// do something
}
before passing to adapter, or
val userSelect: ((UsersTable?) -> Unit) = {
}
at the time of declaration.
I have a little problem with baseContext in Fragment, in a nutshell, I'm making an application with Retrofit and RecyclerView, and for practice I decided to make them in Fragment,I took this code from MainActivity and then I ran into a problem that I don't know how to replace baseContext in override fun onResponse, I just replaced it with context and it still doesn't work
import androidx.lifecycle.ViewModelProvider
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.myapplicationsadas.*
import kotlinx.android.synthetic.main.fragment_main.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MainFragment : Fragment() {
lateinit var mService: RetrofitServices
lateinit var layoutManager: LinearLayoutManager
lateinit var adapter: MyMovieAdapter
companion object {
fun newInstance() = MainFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_main, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
mService = Common.retrofitService
recyclerMovieList.setHasFixedSize(true)
//layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
layoutManager = LinearLayoutManager(context)
recyclerMovieList.layoutManager = layoutManager
getAllMovie()
}
private fun getAllMovie() {
mService.getMovieList().enqueue(object : Callback<MutableList<Movie>>{
override fun onResponse(
call: Call<MutableList<Movie>>,
response: Response<MutableList<Movie>>
) {
adapter = MyMovieAdapter(baseContext, response.body() as MutableList<Movie>)
adapter.notifyDataSetChanged()
recyclerMovieList.adapter = adapter
}
override fun onFailure(call: Call<MutableList<Movie>>, t: Throwable) {
TODO("Not yet implemented")
}
})
}
}
I want to use notification on Fragment. And if I touch button, notification will appear.
I use many ways, and I find one way to use it. but it is not worked. only run like this
2022-06-08 15:30:10.765 28876-28876/com.ebookfrenzy.sample D/MyFragment: startMyService: Intent: Intent { cmp=com.ebookfrenzy.sample/.ui.MyService }
And below one is mainFragment.kt
package com.ebookfrenzy.sample.ui.main
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.ebookfrenzy.sample.databinding.FragmentMainBinding
import com.ebookfrenzy.sample.ui.MyService
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
companion object {
fun newInstance() = MainFragment()
private const val TAG = "MyFragment"
}
private lateinit var viewModel: MainViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentMainBinding.inflate(inflater, container, false)
binding.button.setOnClickListener { startMyService()
}
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun startMyService() {
Intent(context, MyService::class.java).also {
Log.d(TAG, "startMyService: Intent: $it")
// Check Android Policy
context?.startForegroundService(it)
// Less than Android Oreo
context?.startService(it)
}
}
}
MyService
package com.ebookfrenzy.sample.ui
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.annotation.Nullable
import androidx.core.app.NotificationCompat
import com.ebookfrenzy.sample.BuildConfig
import com.ebookfrenzy.sample.R
class MyService : Service() {
companion object {
private const val TAG = "MyService"
}
private val FOREGROUND_ID: Int = 290348
private val foregroundNotificationBuilder: NotificationCompat.Builder
get() = NotificationCompat.Builder(this, applicationContext.packageName).
setSmallIcon(R.mipmap.ic_launcher_round).
setContentTitle("title").
setContentText("content text").
setPriority(NotificationCompat.PRIORITY_HIGH)
override fun onCreate() {
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
startForegroundService()
return START_STICKY
}
#Nullable
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onDestroy() {
super.onDestroy()
stopForeground(true)
}
private fun createNotificationChannel() {
val channelId = applicationContext.packageName
val channelName = BuildConfig.APPLICATION_ID
val channel = NotificationChannel(
channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT
)
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)
}
private fun startForegroundService() {
val notification = foregroundNotificationBuilder.build()
// when Over android oreo, need to notification channel.
createNotificationChannel()
startForeground(FOREGROUND_ID, notification)
}
}
And other codes are not corrected after created
I want to resolve this problem. Please help me...
I have an adapter for my RecyclerView where I program that when I click on the element (of my RecyclerView) it executes an Intent with a putExtra to take me to another activity, the variable that contains my putExtra comes from the element that I clicked, but now I need to add a More variable that comes from the activity. The issue is that I don't know how to send it from the adapter.
this is my adapter.
package com.example.atipicoapp
import android.app.Activity
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.view.menu.ActionMenuItemView
import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.list_item.view.*
class MyAdapter(private val platoList : ArrayList<Plato>
) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter.MyViewHolder {
val itemView =
LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
itemView.platoTouch.setOnClickListener(View.OnClickListener { v: View ->
})
return MyViewHolder(itemView)
}
override fun onBindViewHolder(holder: MyAdapter.MyViewHolder, position: Int) {
val plato: Plato = platoList[position]
holder.platoName.text = plato.platoName
holder.platoDescription.text = plato.platoDescription
holder.platoPrecio.text = plato.platoPrecio.toString()
holder.platoCantidad.text = plato.platoCantidad.toString()
when(holder){
is MyViewHolder -> {
holder.bind(platoList[position])
}
}
}
override fun getItemCount(): Int {
return platoList.size
}
public class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val platoName: TextView = itemView.findViewById(R.id.platoNombre)
val platoDescription: TextView = itemView.findViewById(R.id.platoDescripcion)
val platoPrecio: TextView = itemView.findViewById(R.id.platoPrecio)
val platoTouch: LinearLayout = itemView.findViewById(R.id.platoTouch)
val platoCantidad: TextView = itemView.findViewById(R.id.platoCant)
private val mActivity = itemView.context as Activity
private val intent = Intent(mActivity,SlotActivity::class.java)
fun bind(plato: Plato){
platoTouch.setOnClickListener{
intent.putExtra("id", platoName.text.toString())
mActivity.startActivity(intent)
}
}
}
}
And this is my Activity which contains my RecyclerView and the variable I want to send.
package com.example.atipicoapp
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.firestore.*
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_menu_atipico.*
class MenuAtipicoActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var platoArrayList: ArrayList<Plato>
private lateinit var myAdapter: MyAdapter
private lateinit var db: FirebaseFirestore
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_menu_atipico)
recyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.setHasFixedSize(true)
platoArrayList = arrayListOf()
myAdapter = MyAdapter(platoArrayList)
recyclerView.adapter = myAdapter
pedidoId = intent.extras?.getString("pedidoId") //This is the variable I need to send
EventChangeListener()
Setup()
}
private fun EventChangeListener() {
db = FirebaseFirestore.getInstance()
db.collection("Platos").addSnapshotListener(object : EventListener<QuerySnapshot> {
override fun onEvent(
value: QuerySnapshot?,
error: FirebaseFirestoreException?
) {
if (error != null) {
Log.e("Firestore Error", error.message.toString())
return
}
for (dc: DocumentChange in value?.documentChanges!!) {
if (dc.type == DocumentChange.Type.ADDED) {
platoArrayList.add(dc.document.toObject(Plato::class.java))
}
}
myAdapter.notifyDataSetChanged()
}
})
}
private fun Setup() {
botonAceptar.setOnClickListener {
val SlotIntent = Intent(this, SlotActivity::class.java).apply {
}
startActivity(SlotIntent)
}
}
}
How can I send the variable if the Intent is executed from the Adapter?
Or... If it is not recommended to send intent from my Adapter, how can I send them from the activity?
Knowing that I have to carry a variable that is in the item of the RecyclerView.
Thanks for your help <3
Firstly, create a MyAdapter constructor where you pass arrayList as well as pedidoId like, your MyAdapter should be something like below:
MyAdapter.class
class MyAdapter(private val platoList : ArrayList<Plato>, val pedidoId:String
) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
........
.....
....
//in your bind(..) method
fun bind(plato: Plato){
platoTouch.setOnClickListener{
intent.putExtra("id", platoName.text.toString())
intent.putExtra("pedidoId", pedidoId)
mActivity.startActivity(intent)
}
}
}
And, in your MenuAtipicoActivity you need to do something like:
MenuAtipicoActivity
class MenuAtipicoActivity : AppCompatActivity() {
...............
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_menu_atipico)
recyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.setHasFixedSize(true)
platoArrayList = arrayListOf()
pedidoId = intent.extras?.getString("pedidoId") //This is the variable I need to send
myAdapter = MyAdapter(platoArrayList,pedidoId)
recyclerView.adapter = myAdapter
EventChangeListener()
Setup()
}
..........
........
}