I have a Custom view:
class CustomerView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
private var txtName: TextView
private var txtAge: TextView
init {
View.inflate(context, R.layout.view_customer, null)
txtName = findViewById(R.id.txtTestName)
txtAge = findViewById(R.id.txtTestAge)
txtName.text = "Person"
txtAge.text = "61"
}
}
My Layout view_customer looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/txtTestName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="name" />
<TextView
android:id="#+id/txtTestAge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="age" />
</LinearLayout>
however when I call it in my other page, the app crashes saying
Caused by: java.lang.IllegalStateException:
findViewById(R.id.txtTestName) must not be null
at com.helcim.helcimcommercemobile.customviews.CustomerView.(CustomerView.kt:19)
which is when I am trying to assign txtName
I don't really understand how it is null when I have it in the layout view. and it is named the same.
Am I creating a custom view incorrectly?
You have to add parent layout as parameter to 'inflate' method.
class CustomerView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
private var txtName: TextView
private var txtAge: TextView
init {
View.inflate(context, R.layout.view_customer, this)
txtName = findViewById(R.id.txtTestName)
txtAge = findViewById(R.id.txtTestAge)
txtName.text = "Derek"
txtAge.text = "23"
}
}
Related
I want to add TextInputLayout inside a linearlayout by dynamically. I can add TextView and EditText inside a linearLayout but I can't add TextInputLayout.
that is my LinearLAyout:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="vertical"
android:id="#+id/userInformation_lnr">
I can add TextView and EditText by using following code block
LinearLayout ll = (LinearLayout) findViewById(R.id.userInformation_lnr);
for(int i = 0; i <oyuncuSayisi; i++ ){
EditText et = new EditText(this);
TextView tx = new TextView(this);
tx.setText("Player "+(i+1));
tx.setTextSize(19);
tx.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD_ITALIC));
tx.setTextColor(this.getResources().getColor(R.color.silver));
et.setHint((i+1)+".Enter Player Name");
et.setHintTextColor(this.getResources().getColor(R.color.DarkGoldenrod));
DrawableCompat.setTint(et.getBackground(), ContextCompat.getColor(this, R.color.silver));
et.setTextColor(this.getResources().getColor(R.color.SteelBlue));
et.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD_ITALIC));
et.setTextSize(17);
et.setId((i+1));
ll.addView(tx);
ll.addView(et);
}
But I dont know how to add TextInputLayout, How can add TextInputLayout inside the LinearLayout?
You can decouple presentation and business logic, if you move presentation to xml file.
input_layout.xml
<com.google.android.material.textfield.TextInputLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="#style/MyInputTheme" <-- You can define here your theme or style
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
And create this by LayoutInflater:
LinearLayout container = (LinearLayout) findViewById(R.id.container);
LayoutInflater.from(context).inflate(R.layout.input_layout, container, true);
The TextInputLayout need a TextInputEditText to work, you can make a custom view for your TextInputLayout, then add it to the LinearLayout.
<com.google.android.material.textfield.TextInputLayout 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:id="#+id/tv_input_layout"
style="#style/YourCustomStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:hint="hint"
tools:placeholderText="ex: hint">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/tv_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="value" />
</com.google.android.material.textfield.TextInputLayout>
The class:
class CustomTextInputLayout #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : TextInputLayout(context, attrs, defStyleAttr) {
init {
View.inflate(context, R.layout.custom_input_layout, this)
// set the other things you need
}
}
Then add it to the linearLayout:
private fun createInput() {
val view = CustomTextInputLayout(context)
ll.addView(view)
}
}
You have to add a TextInputLayout with inside a TextInputEditText.
Something like:
LinearLayout myLayout = findViewById(R.id.userInformation_lnr);
TextInputLayout til = new TextInputLayout(this);
til.setHint("Label");
TextInputEditText et = new TextInputEditText(til.getContext());
til.addView(et);
myLayout.addView(til);
The simplest way I found to create a custom view, so I don't have to handle annoying things like to override the onLayout() method, is to make it inherit from a LinearLayout. I also have a LinearLayout at the root of the associated XML file that I inflate, so there is 2 of them at the root.
How can I optimise this, by removing one of this extra LinearLayout, but keep it simple to create custom views ?
MyToolbar.kt:
class MyToolbar #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) :
LinearLayoutCompat(context, attrs, defStyleAttr) {
private val binding = MyToolbarBinding.inflate(LayoutInflater.from(context), this, true)
init {
// [...] Initialization of my view ...
}
}
my_toolbar.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- Actual content of my view -->
</LinearLayout>
What I have right now after #Pawel and #Cata suggestion. This doesn't work, the LinearLayout use the whole height of the parent, but it should only wrap its content.
MyToolbar.kt:
class MyToolbar #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) :
LinearLayoutCompat(context, attrs, defStyleAttr) {
private val binding
init {
// Tried to add the attributes here as they seems ignored on the `merge` tag
gravity = Gravity.CENTER_VERTICAL
orientation = HORIZONTAL
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
binding = MyToolbarBinding.inflate(LayoutInflater.from(context), this)
// [...] Initialization of the view ...
}
}
my_toolbar.xml:
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<!-- Actual content of the view -->
</merge>
As Pawel suggested you could use merge to do that.
This is a sample from the developer website:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Here you can add your custom content views.. -->
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/add"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/delete"/>
</merge>
I'm trying to make my list item to be animated after onClick(),Like Facebook messenger. I tried to do this with animateLayoutChanges=true in my list item layout and also my recyclerView's parent layout, but it is not smooth and have some problem, after first click when I want to show hidden fields (setVisibility(VISIBLE)) , it works not bad, but setVisibility(GONE) works not properly, this is what it looks like
And what I'm trying to achieve is this
Any advice how to do that?
this is My custom view
class MessageItemView : RelativeLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
private var messageTextView: TextView
private var dateTextView: TextView
private var itemView: View? = null
init {
itemView = LayoutInflater.from(context)?.inflate(R.layout.live_chat_list_item, this)
messageTextView = itemView?.findViewById(R.id.live_chat_msg_text_id) as TextView
dateTextView = itemView?.findViewById(R.id.message_received_date_txt_id) as TextView
}
fun setUPViewModelData(message: MessageModel) {
itemView?.setOnClickListener {
dateTextView.visibility = if (dateTextView.visibility == View.VISIBLE) View.GONE else View.VISIBLE
delivered_status_txt_id.visibility = dateTextView.visibility
}
}
And this is xml of this view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical">
<TextView
android:id="#+id/message_received_date_txt_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:visibility="gone" />
<LinearLayout
android:id="#+id/message_wrapper_layout_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/message_received_date_txt_id"
android:orientation="vertical">
<TextView
android:id="#+id/live_chat_msg_text_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView
android:id="#+id/delivered_status_txt_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/message_wrapper_layout_id"
android:visibility="gone" />
</RelativeLayout>
I don't understand what's wrong in my layout hierarchy or what would be good architecture and also interested in Fb's messenger chat item layout hierarchy... Any eideas?
Remove the animateLayoutChanges from your layout and then use the TransitionManager from the support library:
fun setUPViewModelData(message: MessageModel) {
itemView?.setOnClickListener {
TransitionManager.beginDelayedTransition(recyclerView)
dateTextView.visibility = if (dateTextView.visibility == View.VISIBLE) View.GONE else View.VISIBLE
delivered_status_txt_id.visibility = dateTextView.visibility
}
}
I want to create a custom view with 2 TextViews, with possibility change text and text appearances from xml. This view should have two state - normal and selected (TextViews style should be different for each state).
I need some example for it.
Custom views are pretty basic and there are examples all over the internet. For something simple like two text views, it's usually easiest to extend LinearLayout.
Here is the LinearLayout with two text views, arranged side by side.
res/double_text.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/left_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"/>
<TextView
android:id="#+id/right_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"/>
</LinearLayout>
Next we define a styleable resource block so we can add custom attributes to our custom layout.
res/values/attrs.xml
<resources>
<declare-styleable name="DoubleText">
<attr name="leftText" format="string" />
<attr name="rightText" format="string" />
<attr name="android:ems" />
</declare-styleable>
</resources>
Next the class file for DoubleText custom view. In here we pull out the custom attributes and set each of the TextViews.
DoubleTextView.java
public class DoubleTextView extends LinearLayout {
LinearLayout layout = null;
TextView leftTextView = null;
TextView rightTextView = null;
Context mContext = null;
public DoubleTextView(Context context) {
super(context);
mContext = context;
}
public DoubleTextView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DoubleText);
String leftText = a.getString(R.styleable.DoubleText_leftText);
String rightText = a.getString(R.styleable.DoubleText_rightText);
leftText = leftText == null ? "" : leftText;
rightText = rightText == null ? "" : rightText;
String service = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater li = (LayoutInflater) getContext().getSystemService(service);
layout = (LinearLayout) li.inflate(R.layout.double_text, this, true);
leftTextView = (TextView) layout.findViewById(R.id.left_text);
rightTextView = (TextView) layout.findViewById(R.id.right_text);
leftTextView.setText(leftText);
rightTextView.setText(rightText);
a.recycle();
}
public DoubleTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
}
#SuppressWarnings("unused")
public void setLeftText(String text) {
leftTextView.setText(text);
}
#SuppressWarnings("unused")
public void setRightText(String text) {
rightTextView.setText(text);
}
#SuppressWarnings("unused")
public String getLeftText() {
return leftTextView.getText().toString();
}
#SuppressWarnings("unused")
public String getRightText() {
return rightTextView.getText().toString();
}
}
Finally, using the custom class is as simple as declaring it in a layout file.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_main"
tools:context=".MainActivity">
<TextView
android:id="#+id/main_text"
android:text="Hello World!"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/custom"/>
<example.com.test.DoubleTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:leftText="Text Left"
app:rightText="Text Right"
android:layout_below="#+id/main_text"/>
</RelativeLayout>
Easy peasy.
I am trying to create a custom View that would replace a certain layout that I use at multiple places, but I am struggling to do so.
Basically, I want to replace this:
<RelativeLayout
android:id="#+id/dolphinLine"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="#drawable/background_box_light_blue"
android:padding="10dip"
android:layout_margin="10dip">
<TextView
android:id="#+id/dolphinTitle"
android:layout_width="200dip"
android:layout_height="100dip"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dip"
android:text="#string/my_title"
android:textSize="30dip"
android:textStyle="bold"
android:textColor="#2E4C71"
android:gravity="center"/>
<Button
android:id="#+id/dolphinMinusButton"
android:layout_width="100dip"
android:layout_height="100dip"
android:layout_toRightOf="#+id/dolphinTitle"
android:layout_marginLeft="30dip"
android:text="#string/minus_button"
android:textSize="70dip"
android:textStyle="bold"
android:gravity="center"
android:layout_marginTop="1dip"
android:background="#drawable/button_blue_square_selector"
android:textColor="#FFFFFF"
android:onClick="onClick"/>
<TextView
android:id="#+id/dolphinValue"
android:layout_width="100dip"
android:layout_height="100dip"
android:layout_marginLeft="15dip"
android:background="#android:drawable/editbox_background"
android:layout_toRightOf="#+id/dolphinMinusButton"
android:text="0"
android:textColor="#2E4C71"
android:textSize="50dip"
android:gravity="center"
android:textStyle="bold"
android:inputType="none"/>
<Button
android:id="#+id/dolphinPlusButton"
android:layout_width="100dip"
android:layout_height="100dip"
android:layout_toRightOf="#+id/dolphinValue"
android:layout_marginLeft="15dip"
android:text="#string/plus_button"
android:textSize="70dip"
android:textStyle="bold"
android:gravity="center"
android:layout_marginTop="1dip"
android:background="#drawable/button_blue_square_selector"
android:textColor="#FFFFFF"
android:onClick="onClick"/>
</RelativeLayout>
By this:
<view class="com.example.MyQuantityBox"
android:id="#+id/dolphinBox"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:myCustomAttribute="#string/my_title"/>
So, I do not want a custom layout, I want a custom View (it should not be possible for this view to have child).
The only thing that could change from one instance of a MyQuantityBox to another is the title. I would very much like to be able to specify this in the XML (as I do on the last XML line)
How can I do this? Should I put the RelativeLayout in a XML file in /res/layout and inflate it in my MyBoxQuantity class? If yes how do I do so?
Thanks!
A bit old, but I thought sharing how I'd do it, based on chubbsondubs' answer:
I use FrameLayout (see Documentation), since it is used to contain a single view, and inflate into it the view from the xml.
Code following:
public class MyView extends FrameLayout {
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public MyView(Context context) {
super(context);
initView();
}
private void initView() {
inflate(getContext(), R.layout.my_view_layout, this);
}
}
Here is a simple demo to create customview (compoundview) by inflating from xml
attrs.xml
<resources>
<declare-styleable name="CustomView">
<attr format="string" name="text"/>
<attr format="reference" name="image"/>
</declare-styleable>
</resources>
CustomView.kt
class CustomView #JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
ConstraintLayout(context, attrs, defStyleAttr) {
init {
init(attrs)
}
private fun init(attrs: AttributeSet?) {
View.inflate(context, R.layout.custom_layout, this)
val image_thumb = findViewById<ImageView>(R.id.image_thumb)
val text_title = findViewById<TextView>(R.id.text_title)
val ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView)
try {
val text = ta.getString(R.styleable.CustomView_text)
val drawableId = ta.getResourceId(R.styleable.CustomView_image, 0)
if (drawableId != 0) {
val drawable = AppCompatResources.getDrawable(context, drawableId)
image_thumb.setImageDrawable(drawable)
}
text_title.text = text
} finally {
ta.recycle()
}
}
}
custom_layout.xml
We should use merge here instead of ConstraintLayout because
If we use ConstraintLayout here, layout hierarchy will be ConstraintLayout->ConstraintLayout -> ImageView + TextView => we have 1 redundant ConstraintLayout => not very good for performance
<?xml version="1.0" encoding="utf-8"?>
<merge 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"
tools:parentTag="android.support.constraint.ConstraintLayout">
<ImageView
android:id="#+id/image_thumb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="ContentDescription"
tools:src="#mipmap/ic_launcher" />
<TextView
android:id="#+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="#id/image_thumb"
app:layout_constraintStart_toStartOf="#id/image_thumb"
app:layout_constraintTop_toBottomOf="#id/image_thumb"
tools:text="Text" />
</merge>
Using
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<your_package.CustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#f00"
app:image="#drawable/ic_android"
app:text="Android" />
<your_package.CustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0f0"
app:image="#drawable/ic_adb"
app:text="ADB" />
</LinearLayout>
Result
See full code on:
Github
Yes you can do this. RelativeLayout, LinearLayout, etc are Views so a custom layout is a custom view. Just something to consider because if you wanted to create a custom layout you could.
What you want to do is create a Compound Control. You'll create a subclass of RelativeLayout, add all our your components in code (TextView, etc), and in your constructor you can read the attributes passed in from the XML. You can then pass that attribute to your title TextView.
http://developer.android.com/guide/topics/ui/custom-components.html
Use the LayoutInflater as I shown below.
public View myView() {
View v; // Creating an instance for View Object
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.myview, null);
TextView text1 = v.findViewById(R.id.dolphinTitle);
Button btn1 = v.findViewById(R.id.dolphinMinusButton);
TextView text2 = v.findViewById(R.id.dolphinValue);
Button btn2 = v.findViewById(R.id.dolphinPlusButton);
return v;
}
In practice, I have found that you need to be a bit careful, especially if you are using a bit of xml repeatedly. Suppose, for example, that you have a table that you wish to create a table row for each entry in a list. You've set up some xml:
In my_table_row.xml:
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" android:id="#+id/myTableRow">
<ImageButton android:src="#android:drawable/ic_menu_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="#+id/rowButton"/>
<TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="TextView" android:id="#+id/rowText"></TextView>
</TableRow>
Then you want to create it once per row with some code. It assume that you have defined a parent TableLayout myTable to attach the Rows to.
for (int i=0; i<numRows; i++) {
/*
* 1. Make the row and attach it to myTable. For some reason this doesn't seem
* to return the TableRow as you might expect from the xml, so you need to
* receive the View it returns and then find the TableRow and other items, as
* per step 2.
*/
LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.my_table_row, myTable, true);
// 2. Get all the things that we need to refer to to alter in any way.
TableRow tr = (TableRow) v.findViewById(R.id.profileTableRow);
ImageButton rowButton = (ImageButton) v.findViewById(R.id.rowButton);
TextView rowText = (TextView) v.findViewById(R.id.rowText);
// 3. Configure them out as you need to
rowText.setText("Text for this row");
rowButton.setId(i); // So that when it is clicked we know which one has been clicked!
rowButton.setOnClickListener(this); // See note below ...
/*
* To ensure that when finding views by id on the next time round this
* loop (or later) gie lots of spurious, unique, ids.
*/
rowText.setId(1000+i);
tr.setId(3000+i);
}
For a clear simple example on handling rowButton.setOnClickListener(this), see Onclicklistener for a programmatically created button.
There are multiple answers which point the same way in different approaches, I believe the below is the simplest approach without using any third-party libraries, even you can use it using Java.
In Kotlin;
Create values/attr.xml
<resources>
<declare-styleable name="DetailsView">
<attr format="string" name="text"/>
<attr format="string" name="value"/>
</declare-styleable>
</resources>
Create layout/details_view.xml file for your view
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text_label"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.5"
tools:text="Label" />
<TextView
android:id="#+id/text_value"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.5"
tools:text="Value" />
</LinearLayout>
</merge>
Create the custom view widget DetailsView.kt
import android.content.Context
import android.content.res.TypedArray
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import com.payable.taponphone.R
class DetailsView #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
private val attributes: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.DetailsView)
private val view: View = View.inflate(context, R.layout.details_view, this)
init {
view.findViewById<TextView>(R.id.text_label).text = attributes.getString(R.styleable.DetailsView_text)
view.findViewById<TextView>(R.id.text_value).text = attributes.getString(R.styleable.DetailsView_value)
}
}
That's it now you can call the widget anywhere in your app as below
<com.yourapp.widget.DetailsView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:text="Welcome"
app:value="Feb" />
A simple Custom View using Kotlin
Replace FrameLayout with whatever view you Like to extend
/**
* Simple Custom view
*/
class CustomView#JvmOverloads
constructor(context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0)
: FrameLayout(context, attrs, defStyleAttr) {
init {
// Init View
val rootView = (getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
.inflate(R.layout.custom_layout, this, true)
val titleView= rootView.findViewById(id.txtTitle)
// Load Values from XML
val attrsArray = getContext().obtainStyledAttributes(attrs, R.styleable.CutsomView, defStyleAttr, 0)
val titleString = attrsArray.getString(R.styleable.cutomAttrsText)
attrsArray.recycle()
}
}