to sum up I am trying to change the src of ImageButtons inside my dialog_colors.xml file from MainActivity. However whatever I do I couldnt manage to change it. I tried the same code with ImageButtons inside my activity_main.xml but it doesnt work for buttons inside dialog_colors.xml file.
activity_main.xlm
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<include
android:id="@+id/dialog_colors"
layout="@layout/dialog_colors"/> ...
dialog_colors.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_paint_colors"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ImageButton
android:id="@+id/red"
android:layout_width="40sp"
android:layout_height="40sp"
android:src="@drawable/pallet_normal"
android:background="@color/Red"
android:layout_margin="1sp"
android:tag="redTag"
android:clickable="true"
android:onClick="selectColor"
/>...
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
colorDialog=findViewById<LinearLayout>(R.id.dialog_colors)
firstRowColors=colorDialog.findViewById<LinearLayout>(R.id.ll_paint_colors)
secondRowColors=colorDialog.findViewById<LinearLayout>(R.id.ll_paint_colors2)
drawingView=findViewById<DrawingView>(R.id.drawingView)
pressedColor=secondRowColors[0] as ImageButton
pressedColor!!.setImageResource(R.drawable.pallet_pressed)
}...
I tried the same thing with TextViews etc too. It seems like I cannot change anything inside the dialog_colors.xml file.
Do not get confused about the firstRows, secondRows etc, there are many ImageButtons, it doesnt work for any of them.
I found a solution to define an attribute in the MainActivity.kt
through activity_main.xml
to content_main.xml
(included layout). The key word here is DataBinding
. The project is completely reproducible and I provide first Kotlin
and at the very end the JAVA
files.
KOTLIN:
To enable DataBinding
you need to go to your build.gradle(Module)
and add following code:
//...
dataBinding{
enabled true
}
//...
You define a container called DrawableContainer
as a Kotlin
class
. There you define a Drawable
called customDrawable
.
Thus DrawableContainer.kt
:
import android.graphics.drawable.Drawable
data class DrawableContainer(val customDrawable: Drawable)
Now we will define our MainActivity.kt
which will bind our chosen Drawable
and pass it through our Container (DrawableContainer
).
Our MainActivity.kt
:
import android.app.Activity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.example.imagebuttonexperiment.databinding.ActivityMainBinding
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(
this, R.layout.activity_main)
binding.drawable = DrawableContainer(resources.getDrawable(R.drawable.my_image))
}
}
The missing parts are our XML files. The code below shows our content_main.xml
. It contains a variable
(in <data>
) we will define named drawable
. The type
guides to our DrawableContainer
. So this is the first bridge between our Container and our layout we will <include
. In the ImageButton
you can see that as android:src
we refer over our variable
to our Drawable
in our Container. That's why android:src="@{drawable.customDrawable}"
.
Thus content_main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="drawable"
type="com.example.imagebuttonexperiment.DrawableContainer" />
</data>
<ImageButton
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="10dp"
android:src="@{drawable.customDrawable}"/>
</layout>
Now it's important to build our second bridge. Yet, we have DrawableContainer
-> content_main
. This will be the bridge content_main
-> MainActivity
. Therefor we have our <data/>
and variable
defined again. As you can see in <include
we bind:drawable
the exact same variable
which is in both XML
files.
The missing piece in our puzzle is the activity_main.xml
:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<data>
<variable
name="drawable"
type="com.example.imagebuttonexperiment.DrawableContainer" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="@+id/include_content"
layout="@layout/content_main"
bind:drawable = "@{drawable}"/>
</LinearLayout>
</layout>
RESULT:
The final result is an ImageButton
in the MainActivity
that was included by another Layout
. But the Drawable
was chosen from the MainActivity
and passed a Container to be shown in the included Layout
. Magic isn't it!? ;)
JAVA:
And I will keep my word and provide you the JAVA version also.
The XML
files and gradle
will be the same, you only need to use MainActivity.java
instead of MainActivity.kt
, the same for DrawableContainer.java
instead of DrawableContainer.kt
.
Here is the same in green, DrawableContainer.java
:
import android.graphics.drawable.Drawable;
public class DrawableContainer {
public final Drawable customDrawable;
public DrawableContainer(Drawable customDrawable) {
this.customDrawable = customDrawable;
}
}
And of course our MainActivity.java
:
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import com.example.imagebuttonexperiment.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding mainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
mainBinding.setDrawable(new DrawableContainer(getDrawable(R.drawable.my_image)));
}
}
DOWNLOAD PROJECT:
In addition I provide the project with both, JAVA
and Kotlin
classes in it. You just need to comment the content of the 2 classes grey you don't want. In example, if you want to use Kotlin
, grey the content of .java
files.
Documentation & Tutorial: