Welcome to the final part of this Tic Tac Toe Android Kotlin beginner tutorial series. To go to part 1 of this series, click here.
In this tutorial, we’ll change the boring UI that we have so far into this beautiful UI. Let’s get started.

Background Image and Icons
We’ll be using the below image as the background image.

We’ll use the below two images as our custom “X” and “O” placeholders.
Once you’ve downloaded the above images, add them to res/drawables
folder.

Adding The Background Image
Add the below attribute to the Top-Level Parent LinearLayout
. This will set our background image as the background.
android:background="@drawable/background"
We need to update the text color of our TextView
s from Black to White to make them visible in this darker background. Add the below attribute to all 3 TextView
s.
android:textColor="#FFFFFF"
Add the below attributes to the Reset Game Button
widget.
android:background="@android:color/background_light"
android:textStyle="bold"
android:paddingHorizontal="@dimen/layout_margin"
3X3 GameBoard ImageButton
s
Since we’re going to be using the above-shown icons for “X”es and “O”s, we need to change the Button
widgets to the ImageButton
widgets for the 3×3 GameBoard. Once you’ve done that, add the below attributes to the ImageButton
s.
android:layout_width="@dimen/square_btn_size"
android:layout_height="@dimen/square_btn_size"
android:layout_margin="@dimen/btn_margin"
custom_button.xml
To turn the default ImageButton into the one like we have in the image above, we need to customize it a bit. Create a new Drawable Resource File
in the Drawable folder and name it custom_button.
Add the below code to this file. The stroke
is the border around the shape
(rectangle
here). The solid
element gives attributes to fill the shape
. The 99
in the android:color="#992A5BD6"
sets the transparency.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<stroke android:color="#2A5BD6" android:width="5dp"/>
<solid android:color="#992A5BD6"/>
</shape>
Now add this attribute to the ImageButton
s.
android:background="@drawable/custom_button"
Finally, this is what the ImageButton widget should look like.
<ImageButton
android:id="@+id/btnxx"
android:layout_width="@dimen/square_btn_size"
android:layout_height="@dimen/square_btn_size"
android:layout_margin="@dimen/btn_margin"
android:background="@drawable/custom_button"/>
Update Kotlin Code to use “X”-“O” Icons
// Change here
lateinit var buttons: Array<Array<ImageButton>>
// Change here
private fun initButtons(r: Int, c: Int): ImageButton {
// Change here
val btn: ImageButton = findViewById(...)
.
.
.
}
private fun onBtnClick(btn: ImageButton) {
// Change here
if(btn.drawable != null) return
if(player1Turn){
// Change here
btn.setImageResource(R.drawable.cross)
}else{
// Change here
btn.setImageResource(R.drawable.heart)
}
.
.
.
}
private fun clearBoard() {
for (i in 0..2){
for(j in 0..2){
// Change here
buttons[i][j].setImageResource(0)
}
}
roundCount = 0
player1Turn = true
}
Since we’re using Images for “X” and “O”, we’re going to implement a new getField()
function that will return us the text “x” or “o” that is needed in the fields array.
private fun checkForWin(): Boolean {
val fields = Array(3){r->
Array(3){c->
// Change here
getField(buttons[r][c])
}
}
for(i in 0..2){
if((fields[i][0] == fields[i][1])&&
(fields[i][0] == fields[i][2])&&
(fields[i][0] != null)// Change here
)return true
}
for(i in 0..2){
if(
(fields[0][i] == fields[1][i])&&
(fields[0][i] == fields[2][i])&&
(fields[0][i] != null)// Change here
)return true
}
if(
(fields[0][0] == fields[1][1])&&
(fields[0][0] == fields[2][2])&&
(fields[0][0] != null)// Change here
) return true
if(
(fields[0][2] == fields[1][1])&&
(fields[0][2] == fields[2][0])&&
(fields[0][2] != null)// Change here
) return true
return false
}
Here is the getField()
function.
private fun getField(btn: ImageButton): Char? {
val drw: Drawable? = btn.drawable
val drwCross: Drawable? = ResourcesCompat.getDrawable(resources, R.drawable.cross, null)
val drwHeart: Drawable? = ResourcesCompat.getDrawable(resources, R.drawable.heart, null)
return when(drw?.constantState){
drwCross?.constantState -> 'x'
drwHeart?.constantState -> 'o'
else -> null
}
}
Alright, these are all the changes. You can check and run to see if everything is fine.
I hope all of this has been a fun learning experience for you. In case I’ve missed anything, let me know in the comments. This concludes our Android Kotlin Tic Tac Toe Series. See you in the next one.