Kotlin / Migration to View Binding - android

I was following YT video to make Quiz App, but in the end I got this error with binding:
The 'kotlin-android-extensions' Gradle plugin is deprecated.
Please use this migration guide
(https://goo.gle/kotlin-android-extensions-deprecation) to start working with View Binding (https://developer.android.com/topic/libraries/view-binding) and the 'kotlin-parcelize' plugin.
But when I add binding for instance to tv_name.text, i do get error that text is expecting Variable and everything the same with other binding parts.
Libraries part
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import com.example.quizapp.databinding.ActivityResultBinding
Code part
class ResultActivity : AppCompatActivity() {
private val binding by viewBinding(FragmentResultActivity::bind)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_result)
// Hide the status bar.
//window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
val userName = intent.getStringExtra(Constants.USER_NAME)
binding.tv_name.text = userName
val totalQuestions = intent.getIntExtra(Constants.TOTAL_QUESTIONS, 0)
val correctAnswers = intent.getIntExtra(Constants.CORRECT_ANSWERS, 0)
binding.tv_score.text = "Your Score is $correctAnswers out of $totalQuestions."
binding.btn_finish.setOnClickListener {
startActivity(Intent(this#ResultActivity, MainActivity::class.java))
}
}
}

You need to initialize the binding variable properly. Please use the below code:
class ResultActivity : AppCompatActivity() {
private lateinit var binding: ActivityResultBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityResultBinding.inflate(layoutInflater)
setContentView(binding.root)
// Hide the status bar.
//window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
val userName = intent.getStringExtra(Constants.USER_NAME)
binding.tv_name.text = userName
val totalQuestions = intent.getIntExtra(Constants.TOTAL_QUESTIONS, 0)
val correctAnswers = intent.getIntExtra(Constants.CORRECT_ANSWERS, 0)
binding.tv_score.text = "Your Score is $correctAnswers out of $totalQuestions."
binding.btn_finish.setOnClickListener {
startActivity(Intent(this#ResultActivity, MainActivity::class.java))
}
}
}
Since I do not have your resources with me available, I think you might have to change the naming of ActivityResultBinding. However, I am pretty sure this is it.
Happy Coding! :)

First you need to let android know that you are using view binding. so go to "Gradle Scripts" folder and open app level build.gradle(Module:nameOfProject) file and inside android property add this:
android {
// ------ VIEW BINDING SETTING ------
// this creates the binding object
buildFeatures{
viewBinding true
}
// after set up, click on "Sync Now"
}
then in MainActivity.kt:
class MainActivity : AppCompatActivity() {
// Initialize binding object. if ActivityMainBinding is not ready in menu click "Build/Make project"
private lateinit var binding:ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// view Bindig
// binding default layout inflater
binding= ActivityResultBinding.inflate(layoutInflater)
// inflate the root views which is Linear Layout, we access with .root
setContentView(binding.root)
// Set click listeners
....
}

Related

different between call view by name or use binding in android

i'am a newest in android kotlin
I want to know what is the difference between the two lines of code below and which one is better to use
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMaindinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bindins = DataBindingutil.setContentview( this, R.layout.activity_main)
textview.text="text"//or
binding.textview.text="text"
}}
TL;DR There are a few ways of getting views - using view binding is the currently recommended method.
View Binding (recommended)
The recommended way of accessing views is to use view binding. It offers a few advantages over getting the views manually
Less boilerplate code (you don't need to write a bunch of findViewById calls)
Null safety (catches errors like trying to access views from the wrong layout at build time instead of run time)
Type safety - the type of each view is set to help avoid invalid casts
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
// or, without using DataBindingUtil
// binding = ActivityMainBinding.inflate(layoutInflater)
// setContentView(binding.root)
binding.textview.text="text"
}
}
Manually Getting Views
The old way also still works - you can always call findViewById yourself. Keep in mind that it may error or return null if the view is not found or if you try to cast it to the wrong type.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textview = findViewById<TextView>(R.id.textview)
textview.text="text"
}
}
Kotlin Synthetics (deprecated)
Kotlin synthetics were introduced in 2017 to make it easier to get views, but are now deprecated and should be replaced with view binding. With synthetics you would have an import with your layout file name, then you could just access views from it directly.
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textview.text="text"
}
}

Convert FindViewById to Binding

Hi guys how can I change this (FindviewById) to Data Binding because am having issues with
calling the views to the list so I need to change the (fvbi) to (binding) or
can I access my views here when im using the findviewbyid
import android.graphics.Color
import androidx.appcompat.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)
setListeners()
}// end of on create
private fun setListeners() {
val clickableViews: List<View> =
listOf()
for (item in clickableViews) {
item.setOnClickListener { makeColored(it) }
}
}
private fun makeColored(view: View) {
when (view.id) {
// Boxes using Color class colors for background
R.id.box_one_text -> view.setBackgroundColor(Color.DKGRAY)
R.id.box_two_text-> view.setBackgroundColor(Color.GRAY)
// Boxes using Android color resources for background
R.id.box_three_text -> view.setBackgroundResource(android.R.color.holo_green_light)
R.id.box_four_text -> view.setBackgroundResource(android.R.color.holo_green_dark)
R.id.box_five_text -> view.setBackgroundResource(android.R.color.holo_green_light)
else -> view.setBackgroundColor(Color.LTGRAY)
}
}
}
Yes you can access your views with findViewById
val clickableViews: List<View> =
listOf(findViewById(R.id.box_one_text), ...)
or with view binding you can do like this,
val clickableViews: List<View> =
listOf(binding.boxOneText, ...)
Using the binding structure makes more sense now and saves you a lot of code.
eg:if the activity was called HomeActivity it would be ActivityHomeBinding
build.gradle(module)
buildFeatures {
viewBinding true
dataBinding true
}
MainActivity
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityHomeBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.apply {
//eg:
button.setOnClickListener{
}
}
}

What is the cause and sol to the error showing due to view Binding?

On Clicking the btnBmi button, the app is crashing, & in the logcat the error showing for binding code.
I have added the code in the build.gradle file and synced it.
buildFeatures {
viewBinding true
}
// Code for .kt file.
package com.nandini.android.workoutapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.nandini.android.workoutapp.databinding.ActivityBmiCalculatorBinding
class BmiCalculatorActivity : AppCompatActivity() {
private var binding: ActivityBmiCalculatorBinding?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding= ActivityBmiCalculatorBinding.inflate(layoutInflater)
setContentView(binding?.root)
setSupportActionBar(binding?.toolbarBmi)
if(supportActionBar!=null){
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.title="Calculate BMI"
}
binding?.toolbarBmi?.setNavigationOnClickListener {
onBackPressed()
}
}
}
The button to jump on this activity is in the activity_main.xml file with id : btnBmi , & intent code in the MainActivity.kt file.
// in the onCreate method of MainActivity.kt file.
binding?.btnBmi?.setOnClickListener{
val intent = Intent(this#MainActivity,BmiCalculatorActivity::class.java)
startActivity(intent)}
Step 1 change the Parent Theme in the style.xml/theme.xml-
parent="Theme.MaterialComponents.Light.NoActionBar"
Step 2 - Add toolbar in activity_bmi_calculator.xml
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:navigationIcon="#drawable/ic_home_black_24dp" />
Step 3
class BmiCalculatorActivity
: AppCompatActivity() {
lateinit var binding: ActivityBmiCalculatorBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityBmiCalculatorBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.toolbar.title = "Calculate BMI"
binding.toolbar.setNavigationOnClickListener {
onBackPressed()
}
}

I want to get an input from a user of my app through an edittext and when they press a button, it adds the input into a file stored on the device

I'm getting an error stating that I have an unresolved reference in both places where I try a findViewById though both login_button and username are present in my xml file
class LoginPage : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityLoginPageBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLoginPageBinding.inflate(layoutInflater)
setContentView(binding.root)
val button = findViewById<Button>(R.id.login_button)
button.setOnClickListener {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
val name = findViewById<EditText>(R.id.username)
val value: String = name.text.toString()
File("current_users.txt").appendText(value)
}
}
When you use view binding, you don't need to call findViewById(). Instead, use the fields that are generated in the ActivityLoginPageBinding class. For example, you can do binding.login_button if there is an id:+login_button and <Button android:id=#+id/username> in your XML layout. See the View Binding guide for more details.

Why does Kotlin Activity have a problem finding Buttons?

Attempting to update an older Android game project to use view binding. Android Studio version 4.1.3. I am thinking my problem has to do with the naming of my binding class.
the xml file is called activity_correct_guess.xml and I am using what I think is the name that gets generated by the view binding: ActivityCorrectGuessBinding. Appreciate and ideas!
The build errors:
Unresolved reference: ActivityCorrectGuessBinding
Unresolved reference: binding
Unresolved reference: binding
In the Gradle build module I have the following:
android {
compileSdkVersion 30
buildToolsVersion "30.0.0"
buildFeatures {
viewBinding = true
}
layout file: activity_correct_guess.xml
<Button
android:id="#+id/btnPlayAgain"
android:layout_width="wrap_content"
..... />
Activity file: CorrectGuessActivity.kt
class CorrectGuessActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityCorrectGuessBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
playAgain()
exitGame()
}
fun playAgain() {
binding.btnPlayAgain.setOnClickListener {
val intent = Intent("com.appkotlin2021v4.MainActivity")
startActivity(intent)
}
}
Typically, you define your view binding in the root of your Activity or Fragment or in an init block:
class CorrectGuessActivity : AppCompatActivity() {
//get to inflating!
private val binding = ActivityCorrectGuessBinding.inflate(layoutInflater)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
playAgain()
exitGame()
}
fun playAgain() {
binding.btnPlayAgain.setOnClickListener {
val intent = Intent("com.appkotlin2021v4.MainActivity")
startActivity(intent)
}
}
The only time you need to "wait to inflate" is when you're in a non-ViewGroup-based class like RecyclerView.Adapter, etc.
Yes, this is the correct way to define the view binding. thank you!

Categories

Resources