I know this is probably a quite simple question to answer but I want to import my button from activity_main.xml with the id "button1":
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
In the MainActivity.kt so I can add a setOnClickListener to it.
I saw something like this:
MainActivity.kt:
val button1 = findViewById(R.id.button1) as Button
That gives me 2 errors:
unresolved reference: findViewById;
unresolved reference: Button;
This is the action I want to add:
button1.setOnClickListener {
Toast.makeText(applicationContext, "Hello World", Toast.LENGTH_LONG).show()
}
So I could use the setOnClickListener on "button1" but it wont work.
Whats the standard way of importing a button with kotlin so I can use it properly?
So apparently, I needed to add
apply plugin: 'kotlin-android-extensions'
to the build.gradle (Module:app).
After that I was able to import all views via
import kotlinx.android.synthetic.main.activity_main.*
on the MainActivity.kt so I could use the setOnClickListener to the Id I gave the button in the activity_main.xml
I think the findViewById() is just another way to do this, still good. Thanks
You Could Do This:
val button1 = findViewById<Button>(R.id.button1)
In your code, make sure that the Button and findViewById both were referenced from Activity class.
There are different ways for view binding. The recommended one is to use either data binding or view binding feature.
Kotlin synthetics, part of Android Kotlin Extensions Gradle plugin, is Kotlin only method of view binding which doesn't expose nullabilty. That means all the views are declared as platform types. Now beginning from Kotlin 1.4.20, they will not be supported. Check migration to view binding here: https://developer.android.com/topic/libraries/view-binding/migration
findVewbyId is another way for the same purpose, but this comes with some expenses like traversing the view hierarchy to get the view, runtime exceptions, boilerplate code.
Other way is to use library like ButterKnife
Related
New to android development, I'm trying to apply View Binding as they are the recommended view referencing method by Google as of now. I have two layouts content_main.xml and content_note_list.xml. I got the first 'content_main_xml' (MainActivity) to work with View Binding. However I'm having trouble implementing view binding for second 'content_note_list.xml'.
Below is the code that keeps crashing the app within the simulator
here's the image of the code block
It works when I don't use the view binding ie.
setContentView(R.layout.activity_note_list)
but as soon as I try to use the view bindings, it opens up the app and crashes momentarily
setContentView(binding.root)
I don't know what I'm doing wrong, I have followed the description provided by the official android dev site, multiple videos.
Any help would be necessary.
EDIT:
content_note_list.xml activity_note_list.xml
Apologize for attaching image files, the code becomes all messed up when I try to append it.
It seems to be the name. Remembering from android documentation. If your layout is result_profile.xml
<LinearLayout ... >
<TextView android:id="#+id/name" />
<ImageView android:cropToPadding="true" />
<Button android:id="#+id/button"
android:background="#drawable/rounded_button" />
</LinearLayout>
ViewBinding will generate ResultProfileBinding.
If view binding is enabled for a module, a binding class is generated for each XML layout file that the module contains. Each binding class contains references to the root view and all views that have an ID. The name of the binding class is generated by converting the name of the XML file to Pascal case and adding the word "Binding" to the end.
So, with that in mind. if your layout is activity_note_list it will generate ActivityNoteListBinding class or something like that. In your code, you are setting ContentNoteListBinding class. Try to replace ContentNoteListBinding with ActivityNoteListBinding. Also, if it does not solve the problem. Try to add the code from console log. it has more details about the error.
Update
If you want to handle View or ViewGroup which are include in your activity/fragment over <include> tag, you can access these views almost directly. You need to add an Id in this tag <include>. And then you will have access to these components: For example:
This is a activity_note_list.xml
........
<include
id="+#id/ly_content_list_note"
layout="#layout/content_list_note"/>
........
And content_note_list.xml
<listView
id="+id/listNotes"
.......
/>
Now in your Activity class, you can access in this way:
binding.lyContentListNote.listNotes
As you can see, first access directly to the id of the container, which is ly_content_list_note and then all the view components inside that, in this case listNotes.
adding to #rguzman answer, to avoid running into issues like this where the type of the binding is accidentally set wrong, you can use DataBindingUtil library.
For Activity
val binding = DataBindingUtil.setContentView(this, R.layout.your_file)
For Fragments
binding = DataBindingUtil.inflate(inflater, R.layout.your_file, container, false)
//other logic
return binding.root
link to official docs for more info
I have just started Android Development with a basic app which takes the username and display in Toast but came across an error in the main activity. It says "Unresolved references: editName". I tried making the app again, manually importing editText widget and changing the id name but nothing works.
It would be great if someone can tell me what's going wrong.
ScreenShot of the code with error underlined with red..... Module build.... Project build
I'll show you the example in Java.
You must create a variable in your activity class
EditText editName;
then you must override the onCreate() method of the Activity class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
editName = (EditText) findViewById(R.id.editName);
}
overriding the onCreate() you can take a reference to your EditText.
If you're following a tutorial, they're probably expecting you to use Kotlin Synthetic Binding which means you need this in your build.gradle:
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
That will automagically create variables for each View in the layout that has an ID assigned - so if you have an EditText with an ID of editName, then a val editName: EditText will be created in the background when you inflate the layout. Yes it's magic, yes it trips everyone up and accounts for a lot of the problems people run into on here!
Savatore's answer is the normal, standard, non-magical way of doing it. If you want the convenience, look into the View Binding library, which is the official way of automatically binding views to variables (Kotlin synthetics are deprecated)
Here is the tutorial
https://www.youtube.com/watch?time_continue=289&v=OGfZpfn-dGI
In my android studio it doesn't recognize the button iv'e name them
android:id="#+id/top_button"
android:text="top button"
android:text="button 2"
android: android:id="#+id/button_2"
top_button.setOnClicklistner {
println(top button was clicked)
Button_2.setOnClicklistner {
println(Button)
We're missing a lot of context here that would probably help us help you.
A few things first though:
- The android:id property in your XML layout is how you name the View in question. This is most often how you will reference the View in code.
- The android:text property is the user visible text on views like TextView.
- In order for top_button to refer to your desired View in your XML layout file, it needs to be bound in code. There's a couple of normal ways of doing it findViewById() and data-binding.
I'm going to assume, for now, that the last step is what you are missing (it seems the most likely culprit at this point)... Here's a few ways to bind it:
Method 1: when using an Activity class
If you're binding top_button to your View from an Activity class, this should work:
private lateinit var top_button // replace View here with your widget's type
fun onCreate(...) {
super.onCreate(...)
setContentView(R.layout.<i>your_layout_file_name_here</i>)
top_button = findViewById(R.id.top_button)
...
}
Method 2: when using a Fragment class
If you're binding top_button to your View from a Fragment class, it's more like this:
private lateinit var top_button: View // replace View here with your widget's type
fun onCreateView(...): View {
val rootView = layoutInflater.inflate(R.layout.<i>your_layout_file_name_here</i>)
top_button = rootView.findViewById(R.id.top_button)
...
return rootView
}
Method 3: when using data-binding
I prefer this method myself, but you should Google how to setup data-binding in Android as you'll need changes in your build.gradle and all.
First, change your XML layout to be:
<layout>
<!-- your existing layout XML here -->
</layout>
Then in your Activity/Fragment, let's say your XML layout file is named activity_my_cool_screen.xml, you can do:
val binding = ActivityMyCoolScreenBinding.inflate(getLayoutInflater())
binding.topButton.setOnClickListener(...)
Notice here that the ActivityMyCoolScreenBinding class is auto-generated for you. If it turns red at first, then first verify you've accurately setup data-binding in your project, then if that's good to go, make sure to import the ActivityMyCoolScreenBinding class. If you change your XML layout's filename, then the ActivityMyCoolScreenBinding class name will change to match automatically. But, I'd recommend if you do change the name, that you use Android Studio's refactoring/renaming tools as it'll search your codebase and update it everywhere. Otherwise, you have to do it by hand (doable, but potentially tedious and error prone).
Good luck!
if i have this button:
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button" />
which is more advisable in kotlin when it comes to calling views?
this:
val buttonVar: Button = findById(R.id.buuton)
buttonVar.setOnClickListener{
//my code
}
or:
button.setOnClickListener{
//my code
}
When it comes to performance in Kotlin , this is more advisable
button.setOnClickListener{
//my code
}
Because calling views by their ID directly will generate a local view cache.
So the when the view is called the first time kotlin plugin will execute findViewById just a single time, and the next time the view gets called, it will get recovered from the cache . So accesing that view will be faster.
You can refer to this link for more informations enter link description here
I hope this will help you, don't forget to accept the answer if it helps you.
First one is recommended now. The reason is because if you do it the second way, you would be using kotlinx synthetic which is no longer a recommended practice. Source
I am trying to link a function to the onClick property of a button in AndroidStudio but for some reason the system cannot identify the method that I coded.
The funny thing is that it works correctly when I code it in Java. In Kotlin it does not. I updated my Kotlin and checked its configuration but I cannot find the problem. My friend tried the same thing I did in a Linux computer and it worked for him. I have a Mac OS, I don't know if there is some extra configuration to take care of. Can anyone help me?
This is my simple activity:
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun sendMessage(view: View) {
}
}
This is the xml:
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:onClick="sendMessage"
android:text="#string/send_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/editText"
app:layout_constraintTop_toTopOf="parent" />
In build.gradle I have:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
Error message:
Corresponding method handler 'public void sendMessage(android.view.View)' not found
The onClick attribute value should be the name of a method in this View's context to invoke when the view is clicked.
This name must correspond to a public method that takes exactly one parameter of type View. Must be a string value, using '\;' to escape characters such as '\n' or '\uxxxx' for a unicode character
Try to add
tools:context="com.somepackage.MainActivity"
to your top view in xml
It works now. I had to restart AndroidStudio. I still cannot add the function using the attributes window in the design tab but it works if I edit the XML directly.