Creating Custom Views In Android
1.1. Default views
The Android framework provides several default views. The base class a view is the View
. Views are responsible for measuring and drawing themselves and their child elements (in case of a ViewGroup
). Views are also responsible for saving their UI state and handling touch events. Developers can also create custom views and use them in their applications.
It is possible to create custom views by:
- Compound views — combining views with a default wiring
- Custom views — creating your own views
2.a. by extending an existing view, e.g. Button
2.b. by extending the View
class
The following image shows the default view hierarchy of Android.
1.2. Create a new view
Imagine that you have an application that should analyze storage data and give you information with a chart.
1.For first we should create a new class which will extend from ViewGroup, in my case I will extend my view from LinearLayout
class CustomChart @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
var view: View = LayoutInflater.from(context).inflate(R.layout.custom_chart_view, this, false)
init {
addView(view)
drawChart()
}
fun drawChart(i1: Float = 30f, i2: Float = 20F, i3: Float = 20F, i4: Float = 30F) {
val first: LinearLayout = view.findViewById(R.id.first)
val second: LinearLayout = view.findViewById(R.id.second)
val third: LinearLayout = view.findViewById(R.id.third)
val fourth: LinearLayout = view.findViewById(R.id.fourth)
first.layoutParams = getLayoutParams(i1)
second.layoutParams = getLayoutParams(i2)
third.layoutParams = getLayoutParams(i3)
fourth.layoutParams = getLayoutParams(i4)
}
private fun getLayoutParams(weight: Float): LayoutParams {
return LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT, weight)
}
}
I create a very simple example for showing you the main idea of creating a custom view and for that I use a static number of layouts but if you want you can change some part of my code and you can use as many layouts as you want.
2.For Second we should create a new layout file which will the view which user will see.There are some cases when you can not create a xml file but i prefer to have my xml where i can give my desing as how as i want.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
app:cardCornerRadius="71dp"
card_view:cardElevation="0dp"
card_view:contentPadding="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="100"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/first"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/security_chart_background"
android:orientation="horizontal"
tools:ignore="Suspicious0dp" />
<LinearLayout
android:id="@+id/second"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/battery_chart_background"
android:orientation="horizontal"
tools:ignore="Suspicious0dp" />
<LinearLayout
android:id="@+id/third"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/cache_chart_background"
android:orientation="horizontal"
tools:ignore="Suspicious0dp" />
<LinearLayout
android:id="@+id/fourth"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@drawable/cool_chart_background"
android:orientation="horizontal"
tools:ignore="Suspicious0dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
Now we have our view which we can use as other Views or ViewGroups for using it you should only write the name of your View in the XML file. Now we will use our CustomChart in Main Activity and gave him random numbers and it will automatically draw our chart.
Class MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
generateRandomNumbers()
window.statusBarColor = getColor(R.color.statusBar)
}
private fun generateRandomNumbers() {
val shakeAnimation = AnimationUtils.loadAnimation(this, R.anim.shake)
settings.setOnClickListener {
val i1 = (0..20).random() + 10
val i2 = (0..20).random() + 10
val i3 = (0..20).random() + 10
val i4 = (100 - i1 - i2 - i3)
chart.drawChart(i1.toFloat(), i2.toFloat(), i3.toFloat(), i4.toFloat())
cacheContainer.startAnimation(shakeAnimation)
coolContainer.startAnimation(shakeAnimation)
securityContainer.startAnimation(shakeAnimation)
batteryContainer.startAnimation(shakeAnimation)
}
}
}
MainActivity XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView 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"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
tools:context=".MainActivity">
<com.example.cleaner.CustomChart
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="17dp"
app:layout_constraintTop_toBottomOf="@id/space" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>