Convert FindViewById to Binding - android

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{
}
}
}

Related

implement data transfer issue according to viewbinding

The code I wrote is not working because viewbinding is not suitable. I got some help from my friend but I still couldn't do the application please help me my application is interrupted
/*MainActivity*/
class MainActivity : AppCompatActivity() {
private var _binding: ActivityMainBinding?=null//
private val binding
get()=_binding!!
override fun onCreate(savedInstanceState: Bundle?) {
_binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.apply{ //5.işlemimiz ;)
editText
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun aktiviteDegistir (view:View){
val kullaniciVerisi = editText.text.toString()
val intent = Intent(applicationContext,IkinciActivity::class.java)
intent.putExtra("yollananVeri",kullaniciVerisi)
startActivity(intent)//activiteyi başlatım güzel yer
}
/*Activity2*/
val intent = intent//intent
val alinanVeri = intent.getStringExtra("yollananVeri")
textView2.text = alinanVeri
class MainActivity : AppCompatActivity() {
private var _binding: ActivityMainBinding?=null//3.islemimiz
private val binding
get()=_binding!!
override fun onCreate(savedInstanceState: Bundle?) {//4.işlemiiz
_binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.apply{ //5.işlemimiz ;)
editText
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
After adding this code, I waited for the messages to go away, but they didn't.
my application will write something about this to the editText button will be pressed then it needs to come to the textview part in the other activity
you are following approach, that is used to bind in fragment binding. The problem is that you are setting the binding data but not connecting it with the content view. for better approach in activity view binding just the same for more cleaner activity binding.
class MainActivity : AppCompatActivity() {
private lateinit var binder : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binder = ActivityMainBinding.inflate(layoutInflater)
setContentView(binder.root)
viewImpl()
}
/**you view calls...
* like button.setonclick() and all UI related interactions...
*/
private fun viewImpl() {
binder.run {
//here...
}
}
}
In here I have created binding lateinit var for activity binder which will be initialise when binder = ActivityMainBinding.inflate(layoutInflater) and then using that binder reference for setting my content view as setContentView(binder.root).
Happy Coding ✌️.

Android access view binding val outside onCreate activity

I have an activity that has a button. On the button click I want to update text in text view.
I want to use ViewBinding instead of the normal findViewById
This is how I created the val binding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater);
setContentView(binding.root)
binding.btnRoll.setOnClickListener {
rollDice()
}
}
Now in rollDice I want to update the text view but I'm not able to access binding which make sense because its scope is limited to onCreate() , so what is the best practice for this?
private fun rollDice() {
val random = Random().nextInt(6) + 1
binding.txt_random.setText("random")
}
You have two options.
1. Store in a property
Since the inflated content of Activity is fully bound to it's lifecycle, it's safe to keep the reference as a property
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater);
setContentView(binding.root)
binding.btnRoll.setOnClickListener {
rollDice()
}
}
private fun rollDice() {
val random = Random().nextInt(6) + 1
binding.txt_random.setText("random")
}
}
2. Pass the binding to the methods
That's what I usually do, it avoids creating a property where it's not really a necessity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater);
setContentView(binding.root)
binding.btnRoll.setOnClickListener {
rollDice(binding)
}
}
private fun rollDice(binding: ActivityMainBinding) {
val random = Random().nextInt(6) + 1
binding.txt_random.setText("random")
}
}
Both options are valid ways to make the binding visible to Activities methods.
Store the binding in an instance variable on the Activity. Then you have access to it from all the methods in the Activity.
As the question has accepted answer and it is already addressed but here is my approach to the viewBinding
class MainActivity : AppCompatActivity() {
private val binding by lazy{
ActivityMainBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.btnRoll.setOnClickListener {
rollDice()
}
}
private fun rollDice() {
val random = Random().nextInt(6) + 1
binding.txt_random.setText("random")
}
}
I go with lazy initialization of binding so that way it is only intitialized if it is required.
More you can read about lazy initialization here
https://www.baeldung.com/kotlin/lazy-initialization

How to use binding object across functions inside a Kotlin android activity class

I have this class in a file named MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
binding.fab.setOnClickListener {
}
setContentView(binding.root)
}
override fun onResume() {
super.onResume()
fetchData()
displayBudget()
}
private fun fetchData() {
//how to use binding here? for example: binding.tvTotal.setText("0")
}
}
As you can see, I use view binding feature on Android Studio to replace findViewById. How to use binding object (val binding) in fetchData function?
By trial & error, I can use Kotlin's lateinit variable for binding object.
class MainActivity : AppCompatActivity() {
//declare the binding object here
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//initialize the binding object here
binding = ActivityMainBinding.inflate(layoutInflater)
binding.fab.setOnClickListener {
}
setContentView(binding.root)
}
override fun onResume() {
super.onResume()
fetchData()
displayBudget()
}
private fun fetchData() {
//I can use binding object here
binding.tvTotal.setText("0")
}
}
you need to initialize binding as an optional var for the entire class and then set it in the onCreate function and that will allow you to use it on the onResume without a problem
here's how to do it
class MainActivity : AppCompatActivity() {
//what the below does is create a nullable object binding of type ActivityMainBinding
var binding: ActivityMainBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
binding?.fab.setOnClickListener {
}
setContentView(binding.root)
}
override fun onResume() {
super.onResume()
fetchData()
displayBudget()
}
private fun fetchData() {
//you can now access the binding var here by using the ? operator
binding?.tvTotal.setText("0")
}
}
Try this
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding= DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.fab.setOnClickListener {
}
}
}

Why is a property inside aFragment, which is in a ViewPager after showing a Dialog not initialized any more?

As you can see in the images I have a TabLayout and a Viewpager.
I have one Fragment for Products and one for Categories. In my onViewCreated Method I am setting the progressBar visible. The progressBar property is initialized in the onViewCreated Method before accessing the ProgressBar.
As you can see in the image the ProgressBar is set successfully to visible. The products are loaded and afterwards the ProgressBar is set invisible again.
When I hit the Floating Action Button I am opening a Dialog, which is extending the DialogFragment class.
The Main Class, which is containing the TabView and the ViewPager is implementing the ProductDialog.ProductDialogEventListener. This means, when I am hitting the save Button the Method onProductAdded is called in the Main Class.
This Method however is calling a Method in the productFragment Class to add the new Product to the list inside the fragment. When the ProgressBar is set visible now, the I receive a UninitializedPropertyAccessException because the progressBar Property is not initialized.
I don't understand it, because I have already initialized and used it before.
Here is some code:
The ProductDialog:
class ProductDialog : DialogFragment() {
lateinit var editTextTitle: EditText
lateinit var editTextSpecialText: EditText
lateinit var editTextDescription: EditText
lateinit var radioButtonMen: RadioButton
lateinit var radioButtonWomen: RadioButton
lateinit var radioButtonUnisex: RadioButton
lateinit var productDialog: AlertDialog
lateinit var productDialogEventListener: ProductDialogEventListener
lateinit var apiOperations: ApiOperations
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(activity)
val inflater = requireActivity().layoutInflater
val view = inflater.inflate(R.layout.layout_product_dialog,null)
builder.setView(view)
.setTitle("Produkt erstellen")
.setPositiveButton("Speichern") { _, _ -> saveProductRequest()}
.setNegativeButton(R.string.cancel) { _, _ ->
dialog.cancel()
}
setViews(view)
setValues(view)
productDialog = builder.create()
return productDialog
}
interface ProductDialogEventListener{
val onProductAdded: (variant:Product)->Unit
}
override fun onAttach(context: Context?) {
super.onAttach(context)
try {
productDialogEventListener = context as ProductDialogEventListener
}catch (exception: ClassCastException){
throw exception
}
}
private fun onProductSaved(id:String){
productDialogEventListener.onProductAdded(Product(id.toInt(),editTextTitle.text.toString(),editTextSpecialText.text.toString(),editTextDescription.text.toString(),getCheckedGender()))
}
The Main Activity (OverviewActivity)
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.design.widget.TabLayout
import android.support.design.widget.TabLayout.OnTabSelectedListener
import android.support.v4.app.Fragment
import android.support.v4.view.ViewPager
import android.view.View
import android.widget.ListView
import android.widget.ProgressBar
import android.widget.TableLayout
import android.widget.Toast
class OverviewActivity : AppCompatActivity(), ProductDialog.ProductDialogEventListener, CategoryDialog.CategoryDialogListener {
private lateinit var listViewCategories: ListView
private lateinit var apiOperations: ApiOperations
private lateinit var progressBarCategories: ProgressBar
private lateinit var addCategoryButton: FloatingActionButton
private lateinit var tabLayout: TabLayout
private lateinit var viewPager : ViewPager
private var categories = ArrayList<Category>()
private val productsFragment = ProductsFragment()
private val categoriesFragment = CategoriesFragment()
override fun onResume() {
super.onResume()
setCategories()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_overview)
setViews()
setViewPager()
setValues()
}
private fun setViews(){
listViewCategories = findViewById(R.id.listViewCategories)
addCategoryButton = findViewById(R.id.add_category_button)
progressBarCategories = findViewById(R.id.progressCategories)
viewPager = findViewById(R.id.viewPager)
tabLayout = findViewById(R.id.tabLayout)
}
private fun setViewPager(){
val fragmentList = listOf(productsFragment,categoriesFragment)
val overViewPageViewAdapter = OverViewPageViewAdapter(supportFragmentManager,tabLayout.tabCount)
viewPager.adapter = overViewPageViewAdapter
viewPager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout))
tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener{
override fun onTabReselected(p0: TabLayout.Tab?) {
}
override fun onTabUnselected(p0: TabLayout.Tab?) {
}
override fun onTabSelected(tab: TabLayout.Tab) {
viewPager.currentItem = tab.position
}
})
}
private fun setValues(){
apiOperations = ApiOperations(applicationContext)
}
private fun setProgressBarVisible(visible: Boolean, progressBar: ProgressBar){
when(visible){
true -> progressBar.visibility = View.VISIBLE
else -> progressBar.visibility = View.GONE
}
}
fun addNewProductButtonClicked(view:View){
val dialog = ProductDialog()
dialog.show(supportFragmentManager,"New Product")
}
override val onProductAdded: (product: Product) -> Unit
get() = {product ->
productsFragment.onProductAdded(product)
}
}
And finally the productFragment Class
import android.content.Intent
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ListView
import android.widget.ProgressBar
import android.widget.Toast
class ProductsFragment :Fragment(){
lateinit var apiOperations: ApiOperations
lateinit var listViewProducts: ListView
lateinit var addProductButton: FloatingActionButton
lateinit var progressBar: ProgressBar
private var products = ArrayList<Product>()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.products_fragment_layout,container,false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
apiOperations = ApiOperations(view.context)
setViews(view)
setProducts(view)
}
private fun setViews(view: View){
listViewProducts = view.findViewById(R.id.listViewProducts)
addProductButton = view.findViewById(R.id.add_product_button)
progressBar = view.findViewById(R.id.progress_circular)
}
private fun updateProductList(view: View,newList:ArrayList<Product>){
Toast.makeText(context,"settingProgressbar visible",Toast.LENGTH_SHORT).show()
setProgressBarVisible(true)
products = newList
listViewProducts.adapter = ProductListViewAdapter(view,
products,::deleteProduct)
listViewProducts.setOnItemClickListener{ _, _, position, _ ->
val product: Product = listViewProducts.adapter.getItem(position) as Product
openProductActivity(product)
}
setProgressBarVisible(false)
}
private fun setProducts(view: View){
setProgressBarVisible(true)
apiOperations.getProducts(
{ newList -> updateProductList(view,newList)},
{
setProgressBarVisible(false)
Toast.makeText(context,"Produkte konnten nicht geladen werden!",Toast.LENGTH_SHORT).show()
}
)
}
fun addNewProductButtonClicked(view:View){
val dialog = ProductDialog()
dialog.show(fragmentManager,"New Product")
}
private fun deleteProduct(view: View,productId: Int){
setProgressBarVisible(true)
apiOperations.deleteProduct(productId,{
products.removeAll { product -> product.id == productId }
updateProductList(view,products)
setProgressBarVisible(false)
Toast.makeText(view.context,"Produkt wurde gelöscht!", Toast.LENGTH_SHORT).show()
},
{
Toast.makeText(view.context, "Es ist ein Fehler aufgetreten!" , Toast.LENGTH_LONG).show()
setProgressBarVisible(false)
}
)
}
private fun openProductActivity(product: Product){
val intent = Intent(view?.context, ProductActivity::class.java)
intent.putExtra("product",product)
startActivity(intent)
}
private fun setProgressBarVisible(visible: Boolean){
if(progressBar==null){
progressBar = view!!.findViewById(R.id.progress_bar)
}
Toast.makeText(context,"setProgressbar called",Toast.LENGTH_SHORT).show()
when(visible){
true -> progressBar.visibility = View.VISIBLE
else -> progressBar.visibility = View.GONE
}
}
fun onProductAdded(product: Product) {
setProgressBarVisible(true)
products.add(product)
Toast.makeText(context,products.size.toString(),Toast.LENGTH_SHORT).show()
Toast.makeText(context,"Neues Produkt " + product.title + " hinzugefügt!",Toast.LENGTH_SHORT).show()
setProgressBarVisible(false)
}
}
Also I added following Code in the other Fragement. There I have the same issue. It seems like getView() (in Kotlin only view) results in null and hence is not working. Why is this happening. I also tried to reset the values in onResume as recommended in the comments but neither onPause or onResume is called after closing the DialogFragment.
I can't imagine that I am the only one having this problem.
fun onCategoryAdded(category: Category){
Log.i("fragment","onCategoryAdded called")
if(categories === null){
Log.i("fragment", "categories is null")
}
if(view == null){
Log.i("fragment", "view is null")
}
if(categories!=null && view!= null){
categories.add(category)
updateCategoriesList(view!!.context,categories)
}
}
You can create the progressbar inside your activity instead your fragment and then access the progressbar from both your fragments. By doing so, you won't face the error.
The error was accessing the two Fragments initialized at the beginning of the class.
private val productsFragment = ProductsFragment()
private val categoriesFragment = CategoriesFragment()
And that was very stupid, because these were not the fragments that were add to the ViewPager. In the ViewPagerAdapter the Fragments were created and added to the ViewPager.
Thats why I added two methods to the adapter which return the Fragment instances.
In the holding Activity I am calling those before accessing the fragment instances now. And the problem is solved.
The problem was sitting in front of the keyboard.
class OverViewPageViewAdapter(fragmentManager: FragmentManager, private var tabCount: Int) : FragmentStatePagerAdapter(fragmentManager) {
private var productFragment = ProductsFragment()
private var categoriesFragment = CategoriesFragment()
override fun getItem(position: Int): Fragment? {
return when (position) {
0 -> productFragment
1 -> categoriesFragment
else -> null
}
}
override fun getCount(): Int {
return tabCount
}
fun getCategoriesFragmentInstance(): CategoriesFragment{
return categoriesFragment
}
fun getProductFragmentInstance(): ProductsFragment{
return productFragment
}
}
override val onProductAdded: (product: Product) -> Unit
get() = {
product ->
val adapter: OverViewPageViewAdapter = viewPager.adapter as OverViewPageViewAdapter
adapter.getProductFragmentInstance().onProductAdded(product)
}

How to use Tab layout with the data binding library and Kotlin

I'm trying to use Tab Layout + Android Data Binding Library in a Kotlin project, but I'm not succeeding.
Please tell me what I'm doing wrong?
This is mine Activity:
class WoActivity : BaseActivity()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView(this, R.layout.activity_wo) as ActivityWoBinding
binding.wo = WorkOrder()
setSupportActionBar(binding.toolbar)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
binding.setHandler(this);
binding.setManager(getSupportFragmentManager());
}
companion object {
#BindingAdapter("handler") #JvmStatic
fun bindViewPagerAdapter(view: ViewPager, activity: WoActivity) {
val adapter = WOPagerAdapter(activity.supportFragmentManager)
adapter.addFragment(WoTabWoFragment.newInstance(), view.context.getString(R.string.work_order))
adapter.addFragment(WoTabScheFragment.newInstance(), view.context.getString(R.string.scheduling))
view.adapter = adapter
}
#BindingAdapter("pager") #JvmStatic
fun bindViewPagerTabs(view: TabLayout, pagerView: ViewPager) {
view.setupWithViewPager(pagerView, true)
}
}
}
And this is the final result: A empty tab without touch effects

Categories

Resources