Can't implement TextWatcher in kotlin - kotlin

My implementation of TextWatcher
The Error it showing
I am trying to implement TextWatcher in kotlin it got this error. How to fix this

You can simply implement TextWatcher using anonymous class like this:
binding.editText.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
TODO("Not yet implemented")
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
TODO("Not yet implemented")
}
override fun afterTextChanged(p0: Editable?) {
TODO("Not yet implemented")
}
})

Related

How to call canvas from another function?

I am struggling with this problem
I have for example this code
val itemSwipe = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT), DialogFragmentNoticias.DialogFragmentDismissListener {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
return false
}
override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
super.onChildDraw(c, recyclerView, viewHolder, 0f, dY, actionState, isCurrentlyActive);
}
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
}
override fun DialogNoticiasDismiss() {
viewHol?.let {
adapter.notifyItemChanged(it)
allowed = true
}
}
}
I have extended an interface to make a listener, and what I am looking for is use the parameters like c:Canvas or viewHolder:RecyclerView.ViewHolder
in this function listener
override fun DialogNoticiasDismiss() {
viewHol?.let {
adapter.notifyItemChanged(it)
allowed = true
}
}
How do I manage to do this? Any ideas will help a lot
Thank you in advance

I am trying to create a RecyclerView in Kotlin but having what seems a simple issue

So im trying to create a RecyclerView but im getting errors on "class RecyclerAdapter" and "override fun onBindViewHolder" Reference photo down below
On the first it states "Class 'RecyclerAdapter' is not abstract and does not implement abstract base class member public abstract fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int): Unit defined in androidx.recyclerview.widget.RecyclerView.Adapter"
The second error states "onBindViewHolder' overrides nothing"
im am following this tutorial https://www.youtube.com/watch?v=ai9rSGcDhyQ&ab_channel=CodePalace Here the snippet from the tutorial that Im having problems with
I copied the tutorial almost word for word but I have no idea why im still getting these erros and trust me I have tried researching here and elsewhere including android documentation for solutions but to no avail. Here is what I tried to try to fix it:When I added RecyclerView.Viewholder both errors disappear but then the variables become unresolved
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
holder.itemTitle.text=titles[position]
holder.itemDetail.text=details[position]
holder.itemPicture.setImageResource(images[position])
}
I would be very grateful if you can find a solution to this issue.
thank you
class RecyclerAdapter (private var titles:List<String>,private var details: List<String>,private var
images:List<Int>):
RecyclerView.Adapter<RecyclerView.ViewHolder>(){
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val itemTitle: TextView = itemView.findViewById(R.id.title)
val itemDetail:TextView=itemView.findViewById(R.id.description)
val itemPicture: ImageView =itemView.findViewById(R.id.iv_image)
init {
// Define click listener for the ViewHolder's View.
itemView.setOnClickListener{v:View->
val position:Int =adapterPosition
Toast.makeText(itemView.context," You clicked on item #
${position+1}",Toast.LENGTH_SHORT)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v =LayoutInflater.from(parent.context).inflate(R.layout.item_layout,parent,false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemTitle.text=titles[position]
holder.itemDetail.text=details[position]
holder.itemPicture.setImageResource(images[position])
}
override fun getItemCount(): Int {
return titles.size
}
}
RecyclerAdapter.ViewHolder, not RecyclerView.ViewHolder
class RecyclerAdapter (private var titles:List<String>,private var details: List<String>,private var
images:List<Int>):
RecyclerView.Adapter<RecyclerAdapter.ViewHolder>()

Kotlin: How to fetch data from web service and display it in app?

Hello :) I'm working on app that shows popular movies and some details about each of them. I created a RecyclerView where information should be displayed. I'm stuck with getting and displaying data. I'm using https://www.themoviedb.org/ page for api.
I was following these steps: http://imakeanapp.com/make-a-movies-app-using-tmdb-api-part-4-networking-using-retrofit-library/ , but it's written in Java and I need code in Kotlin. I converted by myself a part of the code, here is what I have:
in Movie.kt
data class Movie (
#SerializedName("id") val id: Int,
#SerializedName("title") val title: String,
#SerializedName("poster_path") val posterPath: String,
#SerializedName("release_date") val releaseDate: String,
#SerializedName("vote_average") val rating: Float
)
in MoviesResponse.kt
data class MoviesResponse (
#SerializedName("page") val page: Int,
#SerializedName("total_results") val totalResults: Int,
#SerializedName("results") val movies: List<Movie>,
#SerializedName("total_pages") val totalPages: Int
)
in TMDbApi.kt
interface TMDbApi {
#GET("movie/popular")
fun getPopularMovies (
#Query("api_key") apiKey: String,
#Query("language") language: String,
#Query("page") page: Int
): Call<List<MoviesResponse>>
}
in OnGetMoviesCallback.kt
interface OnGetMoviesCallback {
fun onSuccess(movies: List<Movie>)
fun onError()
}
in MainAdapter.kt
class MainAdapter: RecyclerView.Adapter<CustomHolder>(){
var movies: List<Movie> = listOf()
fun MainAdapter(movies: List<Movie>) {
this.movies = movies
}
override fun getItemCount(): Int {
return movies.size
}
override fun onBindViewHolder(holder: CustomHolder, position: Int) {
holder.bind(movies.get(position))
holder?.setOnClick()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomHolder {
val layoutInflater = LayoutInflater.from(parent?.context)
val cellForRow = layoutInflater.inflate(R.layout.movie_row, parent, false)
return CustomHolder(cellForRow)
}
}
class CustomHolder(view: View): RecyclerView.ViewHolder(view){
fun bind(result: Movie){
itemView.title.text = result.title
itemView.release_date.text = result.releaseDate
}
}
in MoviesRepository.kt
val BASE_URL: String = "https://api.themoviedb.org/3/"
val LANGUAGE: String = "en-US"
data class MoviesRepository (
val repositroy: MoviesRepository,
val api: TMDbApi
)
object getInstance{
val retrofit: TMDbApi = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.client(OkHttpClient().newBuilder().build())
.baseUrl(BASE_URL)
.build()
.create(TMDbApi::class.java)
}
in AllMoviesActivity.kt
class AllMoviesActivity : AppCompatActivity(), Callback<List<MoviesResponse>> {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_all_movies)
rw_main.layoutManager = LinearLayoutManager(this)
rw_main.adapter = MainAdapter()
getMovies()
}
private fun getMovies() {
getInstance.retrofit.getPopularMovies("2B0b0e8d104f0d6130a4fc67848f89e107", LANGUAGE, 1).enqueue(this)
}
override fun onResponse(call: retrofit2.Call<List<MoviesResponse>>, response: Response<List<MoviesResponse>>) {
val moviesResponse = response.body() ?: listOf()
Log.d("Results", moviesResponse.toString())
}
override fun onFailure(call: retrofit2.Call<List<MoviesResponse>>, t: Throwable) {
Toast.makeText(this, "Failed", Toast.LENGTH_SHORT).show()
}
}
And I have added in Manifest file Internet permission. When I run this, I get 'Failed' Toast and I don't see RecyclerView. Can you tell me what I'm missing or what's wrong? I've been searching on the Internet solutions but with no results. Hope you could help me. Thanks!
Looks like you are missing something small. After making a call to the API on Postman, Here's what you expect on your response body:
{
"page": 1,
"total_results": 10000,
"total_pages": 500,
"results": [...
}
Having brought that up, lets digest your lines, in TMDbApi.kt, you have indicated that your expected response is a List<MoviesResponse> which conflicts the response you receive as it is a JSON of type MoviesResponse,
Fix:
...): Call<List<MoviesResponse>>
}
to:
): Call<MoviesResponse>
}
The rest are small fixes to align your response handling.
Head over to AllMoviesActivity.kt and change the following:
class AllMoviesActivity : AppCompatActivity(), Callback<List<MoviesResponse>> {
to
class MainActivity : AppCompatActivity(), Callback<MoviesResponse>
Then on the callback functions, change signatures like so:
override fun onResponse(call: retrofit2.Call<List<MoviesResponse>>, response: Response<List<MoviesResponse>>) {
val moviesResponse = response.body() ?: listOf() ...
to:
override fun onResponse(call: Call<MoviesResponse>, response:Response<MoviesResponse>
) {
val moviesResponse = response.body()//type will be inferred ...
Then finally,
override fun onFailure(call: retrofit2.Call<List<MoviesResponse>>, t: Throwable) {
to:
override fun onFailure(call: Call<MoviesResponse>, t: Throwable) {
That's the basic to get the response and keep the Failure toast at bay.
Parting shot
Make the logs your friend, they can reveal the messy & smallest misses

kotlin.NotImplementedError: An operation is not implemented: not implemented

Server JSON Data parsing using retrofit2 and rxjava2. Data get and successfully stored in List when go to CompanyAdapter class then give above error.
MainActivity.kt
private fun fetchData(){
val retrofit = APIClient.apIClient
if (retrofit != null) {
api = retrofit.create(APIInterface::class.java)
}
compositeDisposable!!.add(api.getCompanyData()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe{displayData(it.company)
}
)
}
private fun displayData(companyList : List<Company>) {
adapter = CompanyAdapter(this, companyList)
rvCompany.adapter = adapter
}
ComnyAdapter.kt
class CompanyAdapter(internal var context: Context, internal var companyList: List<Company>)
:RecyclerView.Adapter<CompanyAdapter.CompanyViewHolder>()
{
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CompanyViewHolder {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
val itemView = LayoutInflater.from(p0.context).inflate(R.layout.list_view_item,p0,false)
return CompanyViewHolder(itemView)
}
override fun getItemCount(): Int {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
return companyList.size
}
override fun onBindViewHolder(p0: CompanyViewHolder, p1: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
p0.bindModel(companyList[p1])
}
inner class CompanyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val radioButton : RadioButton = itemView.findViewById(R.id.rbCompanyName)
fun bindModel(company: Company){
radioButton.text = company.Cmp_Name
}
}
}
The reason is simple: when you exec a line with TODO, it throws a Not Implemented Exception.
Just remove all the TODO from your code:
class CompanyAdapter(internal var context: Context, internal var companyList: List<Company>)
:RecyclerView.Adapter<CompanyAdapter.CompanyViewHolder>()
{
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CompanyViewHolder {
val itemView = LayoutInflater.from(p0.context).inflate(R.layout.list_view_item,p0,false)
return CompanyViewHolder(itemView)
}
override fun getItemCount(): Int {
return companyList.size
}
override fun onBindViewHolder(p0: CompanyViewHolder, p1: Int) {
p0.bindModel(companyList[p1])
}
inner class CompanyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val radioButton : RadioButton = itemView.findViewById(R.id.rbCompanyName)
fun bindModel(company: Company){
radioButton.text = company.Cmp_Name
}
}
}

kotlin - Check if editText content has been modifed by user or programmatically

I have 2 editTexts. When editText1 is modified, editText2 content will equal to editText1 * 5. When editText2 is modified, editText1 content will be equal to editText2 * 5.
Now, if I use addTextChangedListener() it goes in loops beacause editTexts content will change always causing a crash. I need to detect if editTexts are modified by user or programmatically.
Any idea?
If can help, here's my code:
fun EditText.doubleValue() = text.toString().toDoubleOrNull() ?: 0.0
editText1.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
editText2.setText(editText1.doubleValue() * 5)
}
})
editText2.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
editText1.setText(editText2.doubleValue() * 5)
}
})
EDIT: SOLVED
I used if(editText.isFocused) to check if was changed by user
You can save the TextWatchers in variables, remove them before programatically changing the content of each TextView then add them back again.
class MyActivity: AppCompatActivity() {
private val textWatcher1 = object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
updateEditText2()
}
}
fun EditText.doubleValue() = text.toString().toDoubleOrNull() ?: 0.0
private val textWatcher2 = object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
updateEditText1()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
editText1.addTextChangedListener(textWatcher1)
editText2.addTextChangedListener(textWatcher2)
}
private fun updateEditText1() {
editText1.removeTextChangedListener(textWatcher1)
editText1.setText(editText2.doubleValue() * 5)
editText1.addTextChangedListener(textWatcher1)
}
private fun updateEditText2() {
editText2.removeTextChangedListener(textWatcher2)
editText2.setText(editText1.doubleValue() * 5)
editText2.addTextChangedListener(textWatcher2)
}
}
I think your best option would be to use the actionDone ime option. This way only when the user is done editing the field the other edit text will be updated.
To do that you would need to add android:imeOptions="actionDone" to your editText xml el elements. Then in your code instead of listening for changes you would add an action listener:
editText1.setOnEditorActionListener() { v, actionId, event ->
if(actionId == EditorInfo.IME_ACTION_DONE){
editText2.setText(editText1.doubleValue() * 5)
true
} else {
false
}
}
Without knowing you use case I don't know if this solution will work for you. If you need to update the editTexts in real time maybe checking if the field is in focus could prevent the infinit loop:
editText1.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
if(editText1.hasFocus()) {
editText2.setText(editText1.doubleValue() * 5)
}
}
})
First of all, remove the function doubleValue(), it does not work (or at least I could not make it work).
Use 2 boolean variables from1 and from2, indicating that the change that is about to be done is from code and check their values inside the watchers.
Say that you type inside editText1.
The textwatcher of editText1 before changing the value of editText2 sets from1 = true.
When the text of editText2 changes, the textwatcher of editText2 checks the value of from1 and because it is true does nothing, only sets from1 = false.
var from1 = false;
var from2 = false;
editText1.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
if (from2) {
from2 = false
} else {
val value = editText1.text.toString().toDoubleOrNull() ?: 0.0
from1 = true
editText2.setText((value * 5).toString())
}
}
})
editText2.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun afterTextChanged(editable: Editable) {
if (from1) {
from1 = false
} else {
val value = editText2.text.toString().toDoubleOrNull() ?: 0.0
from2 = true
editText1.setText((value * 5).toString())
}
}
})