Hello friends, Today we will see how to use butter knife library in kotlin with a sample project.
Butter knife in java have many tutorials but in kotlin you need to struggle.
What is butter knife
- Butter knife is View Injection library
Why we need it.
Every time finding view by findViewById, declaring them and then perform events like setText, set color, Now using butter knife we can Bind View as @BindView and use them any where.
1. Adding Butter Knife Dependency.
Add this line to build.gradle at the top below apply plugin: 'com.android.application'
Here with code you can see ButterKnife.bind(this) statement keep it in mind and lets add xml layout for MainActivity as activity_main.xml
Now we will consider you know how to show fragment in activity in Kotlin, For those directly starting from this post just look at our previous blog how to add fragment in activity kotlin
Now we have to add fragment and xml layout for fragment so to cover maximum points of butter knife we have added few more widget components on xml layout of fragment
TextView :- To show use of @BindView
ImageView :- To show use of @BindDrawable and set them to imageview
Button :- To show use of @onClick listener
5 TextView inside cardview :- To show usage of action.
Now we will see code of MainFragment to get whole picture. but first layout of fragment_main.xml
@BindView : -
@BindViews :-
Similar to bindView but can be used to bind multiple view of same type to perform a comman operation like setText using butter knife ACTION
Bind 5 textview to a mutable list. If you are using normal list then use @JvmField, when using @JvmField you can not use lateinit keyword.
@onClick :-
Bind ButterKnife library to your activity and fragment unless it is added you will get run time exceptions as lateinit field not initialized.
To bind it to fragment declare
Unbind it to avoid memory leaks like as below.
ACTION :-
actions are used to perform repeating task. like we have multiple textview and they need to populated with sum text run time so instead of binding them to field and assign values them one by one
bind those multiple textviews to a mutable list and keep all the text in array which is going to assing and create one action like below.
Now see at complete source code of MainFragment
MainFragment.ktl
Like @BindView and @BindViews there are more tags like
@BindInt
@BinfString
@BindDrawable
@BindFloat
@BindFont
@BindBitmap
@BindAnim
@BindDimen
@BindColor
These are all similar to @BindView try them by yourself. and enjoy.
Butter knife in java have many tutorials but in kotlin you need to struggle.
What is butter knife
- Butter knife is View Injection library
Why we need it.
Every time finding view by findViewById, declaring them and then perform events like setText, set color, Now using butter knife we can Bind View as @BindView and use them any where.
1. Adding Butter Knife Dependency.
Add this line to build.gradle at the top below apply plugin: 'com.android.application'
apply plugin: 'kotlin-kapt'
Add dependancydependencies { ...
implementation 'com.jakewharton:butterknife:8.8.1'
kapt 'com.jakewharton:butterknife-compiler:8.8.1'
}
2. Usage of View Binding
We will see it by example code with one activity and a fragment to it added dynamically.
Lets see MainActivity.ktl
import android.support.v7.app.AppCompatActivity import android.os.Bundle import butterknife.ButterKnife class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) ButterKnife.bind(this) val fragment = MainFragment.newInstance("MainFragment") supportFragmentManager.beginTransaction().add(R.id.container, fragment, "fragment").commit() } }
Here with code you can see ButterKnife.bind(this) statement keep it in mind and lets add xml layout for MainActivity as activity_main.xml
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.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"android:id="@+id/container"tools:context="com.fd.butterknifesample.MainActivity"> </android.support.constraint.ConstraintLayout>
Now we will consider you know how to show fragment in activity in Kotlin, For those directly starting from this post just look at our previous blog how to add fragment in activity kotlin
Now we have to add fragment and xml layout for fragment so to cover maximum points of butter knife we have added few more widget components on xml layout of fragment
TextView :- To show use of @BindView
ImageView :- To show use of @BindDrawable and set them to imageview
Button :- To show use of @onClick listener
5 TextView inside cardview :- To show usage of action.
Now we will see code of MainFragment to get whole picture. but first layout of fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="com.fd.butterknifesample.MainActivity"> <TextView android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:gravity="center"
android:text="@string/label_demo"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@+id/imageViewDemo"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/buttonDemo"
android:layout_width="wrap_content"
android:layout_height="51dp"
android:layout_marginBottom="144dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textInputLayoutDemo" /> <TextView android:id="@+id/textViewDemo"
android:layout_width="208dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:text="TextView"
app:layout_constraintBottom_toTopOf="@+id/textInputLayoutDemo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.247"
app:layout_constraintStart_toEndOf="@+id/imageViewDemo"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintVertical_bias="0.2" /> <ImageView android:id="@+id/imageViewDemo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="28dp"
android:layout_marginStart="28dp"
android:contentDescription="@string/imageView_contentDesc"
android:src="@android:drawable/dialog_frame"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView"
app:layout_constraintVertical_bias="0.1"
tools:layout_editor_absoluteY="74dp" /> <android.support.design.widget.TextInputLayout
android:id="@+id/textInputLayoutDemo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:hint="Enter your name"
app:layout_constraintBottom_toTopOf="@id/buttonDemo"
app:layout_constraintTop_toBottomOf="@id/imageViewDemo"
app:layout_constraintVertical_bias=".30"
tools:layout_editor_absoluteY="169dp"> <android.support.design.widget.TextInputEditText
android:id="@+id/textInputEditDemo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="hint" /> </android.support.design.widget.TextInputLayout> <android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/buttonDemo"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="400dp"> <android.support.v7.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"> <TextView android:text="textView 1"
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp" /> <TextView android:text="textView 2"
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp" /> <TextView android:text="textView 3"
android:id="@+id/textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp" />
<TextView android:text="textView 4"
android:id="@+id/textView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp" /> <TextView android:text="textView 5"
android:id="@+id/textView5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp" /> </android.support.v7.widget.LinearLayoutCompat> </android.support.v7.widget.CardView> </android.support.constraint.ConstraintLayout>
In kotlin we can not keep any field as null like as Java to attain NullSafety so while binding views we use lateinit keyword of kotlin.
@BindView : -
bind a single view to field "mTextViewDemo" and use it anywhere.@BindView(R.id.textViewDemo) lateinit var mTextViewDemo: TextView
@BindViews :-
Similar to bindView but can be used to bind multiple view of same type to perform a comman operation like setText using butter knife ACTION
Bind 5 textview to a mutable list. If you are using normal list then use @JvmField, when using @JvmField you can not use lateinit keyword.
//BindViews @BindViews(R.id.textView1, R.id.textView2, R.id.textView3, R.id.textView4, R.id.textView5) lateinit var labelArray: MutableList<TextView>
@onClick :-
@OnClick(R.id.buttonSample) internal fun sayHello() { Toast.makeText(this, "Hello butter knife from kotlin", LENGTH_SHORT).show() }
Bind ButterKnife library to your activity and fragment unless it is added you will get run time exceptions as lateinit field not initialized.
To bind it to fragment declare
var mUnbinder: Unbinder? = nullNow bind it in onCreateView of Fragment as below
//Bind this view to butterknife
mUnbinder = ButterKnife.bind(this, rootView!!)
Unbind it to avoid memory leaks like as below.
override fun onDestroyView() { super.onDestroyView() //unbind view from butterknife to avoid any memory leak
mUnbinder!!.unbind() }
ACTION :-
actions are used to perform repeating task. like we have multiple textview and they need to populated with sum text run time so instead of binding them to field and assign values them one by one
bind those multiple textviews to a mutable list and keep all the text in array which is going to assing and create one action like below.
//Create action to set values to list of textViewval action_set_text = ButterKnife.Action<TextView?> { view, index -> view.setText(mLabel[index]) }
ButterKnife.apply(labelArray, action_set_text)
Now see at complete source code of MainFragment
MainFragment.ktl
package com.fd.butterknifesample import android.content.Context import android.graphics.Color import android.graphics.drawable.Drawable import android.os.Bundle import android.support.annotation.ColorIntimport android.support.design.widget.TextInputEditText import android.support.design.widget.TextInputLayout import android.support.v4.app.Fragment import android.support.v4.text.TextUtilsCompat import android.text.TextUtils import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.ImageView import android.widget.TextView import android.widget.Toast import butterknife.* /** * Created by Jayesh on 2/19/2018. */class MainFragment : Fragment() { var mUnbinder: Unbinder? = null var mParam: String? = null // BindView @BindView(R.id.textViewDemo) lateinit var mTextViewDemo: TextView @BindView(R.id.textInputEditDemo) lateinit var mTextInputLayoutDemo: TextInputEditText @BindView(R.id.imageViewDemo) lateinit var mImageViewDemo: ImageView //BindViews @BindViews(R.id.textView1, R.id.textView2, R.id.textView3, R.id.textView4, R.id.textView5) lateinit var labelArray: MutableList<TextView> //Bind Color @JvmField @BindColor(android.R.color.white) @ColorInt internal var mColor: Int = 0 //Bind Drawable @JvmField @BindDrawable(R.mipmap.ic_launcher) var mDrawable: Drawable? = null @JvmField @BindView(R.id.buttonDemo) var mButton: Button? = null var mLabel = arrayOf<String>("One", "Two", "Three", "Four", "Five") var mLabelColor = arrayOf<Int>(Color.BLACK, Color.BLUE, Color.GREEN, Color.MAGENTA, Color.YELLOW) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (arguments != null) { mParam = arguments.getString(ARG_PARAM) } } override fun onDestroyView() { super.onDestroyView() //unbind view from butterknife to avoid any memory leak mUnbinder!!.unbind() } override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View { val rootView: View? = inflater?.inflate(R.layout.fragment_main, container, false); //Bind this view to butterknife mUnbinder = ButterKnife.bind(this, rootView!!) //Create action to set values to list of textView val action_set_text = ButterKnife.Action<TextView?> { view, index -> view.setText(mLabel[index]) } ButterKnife.apply(labelArray, action_set_text) val action_change_color = ButterKnife.Action<TextView> { view, index -> view.setTextColor(mLabelColor[index]) } ButterKnife.apply(labelArray, action_change_color) // Set Drawable to ImageView mImageViewDemo?.setImageDrawable(mDrawable!!) mButton?.setOnClickListener { if (!TextUtils.isEmpty(mTextInputLayoutDemo?.text.toString())) mTextViewDemo?.text = mTextInputLayoutDemo?.text.toString() else Toast.makeText(activity!!, "Type some text first", Toast.LENGTH_SHORT).show() } //Now assign ONCLICK @OnClick(R.id.buttonDemo) fun onButtonClick() { if (!TextUtils.isEmpty(mTextInputLayoutDemo?.text.toString())) mTextViewDemo?.text = mTextInputLayoutDemo?.text.toString() else Toast.makeText(activity!!, "Type some text first", Toast.LENGTH_SHORT).show() } return rootView!!; } override fun onAttach(context: Context?) { super.onAttach(context) } companion object { val ARG_PARAM: String = "PARAM1" fun newInstance(param: String): MainFragment { val fragment = MainFragment() var arg: Bundle = Bundle() arg.putString(ARG_PARAM, param) fragment.arguments = arg return fragment } } @OnClick(R.id.buttonSample) internal fun sayHello() { Toast.makeText(this, "Hello butter knife from kotlin", LENGTH_SHORT).show() } }
Like @BindView and @BindViews there are more tags like
@BindInt
@BinfString
@BindDrawable
@BindFloat
@BindFont
@BindBitmap
@BindAnim
@BindDimen
@BindColor
These are all similar to @BindView try them by yourself. and enjoy.