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);
Related
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 want to set button style programmatically. Reason for that is I have CustomView containing Button. I send style id to my CustomView using custom parameter inside <declare-styleable>. Now I need to set button style for only Button not whole view in my CustomView.
CustomView:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="40dp"
android:layout_height="40dp"
android:indeterminate="true"
android:layout_gravity="center"
android:indeterminateTint="#color/colorText"/>
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>
CustomView in my code:
<myproject.CustomView
android:id="#+id/btn"
app:progressColor="#color/colorText"
app:l_buttonText="#string/text"
app:l_buttonStyle="#style/dialog_outlined"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="48dp" />
What I want to achieve is to set style for Button only (value obtained from app:l_buttonStyle) But I have to do this programmatically, because if I set style in XML it will be applied to FrameLayout as a root view. Here is function to init parts of my CustomView
private fun init(context: Context) {
//Init default values
View.inflate(context, R.layout.loading_button, this)
button = findViewById(R.id.button)
progressBar = findViewById(R.id.progressBar)
progressBar?.setGone()
//Now I need to set style for my inflated Button from XML layout
}
The views in custom view has to be created programmatically and at the time of initializing the view custom style has to be applied. Once the view is initialized, style cannot be set.
val button = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Button(this, null, 0, R.style.BtnStyle)
} else {
var themeWrapper = ContextThemeWrapper(this, R.style.BtnStyle)
Button(themeWrapper, null, 0)
}
How to align the error text message to the center and below of edittext.I tried to align but its not working.Here is my code:
Xml
<android.support.design.widget.TextInputLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/tilEmail">
<EditText
android:layout_width="match_parent"
android:id="#+id/mob"
android:layout_height="35dp"
android:background="#drawable/round_corner_3"
android:inputType="phone"
android:hint="Mobile Number"
android:textColorHint="#color/colorGray"
android:textColor="#color/Black"
android:drawablePadding="10dp"/>
</android.support.design.widget.TextInputLayout>
Java class
til = (TextInputLayout) findViewById(R.id.tilEmail);
til.setError("Mobile number not valid");
til.setError(Html.fromHtml("<font color='red'>Mobile number not valid</font>"));
mobile.setError(null);
mobile.getBackground().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
Toast.makeText(getApplicationContext(), "Phone number or Password is not valid", Toast.LENGTH_SHORT).show();
}
// reference an error textview
TextView textView = (TextView) til.findViewById(android.support.design.R.id
.textinput_error);
if (textView != null) {
// can be RelativeLayout/FrameLayout Params, depending on your xml
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) textView.getLayoutParams();
params.gravity = Gravity.CENTER|Gravity.BOTTOM;
textView.setLayoutParams(params);
}
Additionally, you can add margins to LayoutParams
You need to create a custom class extending TextInputLayout and set the gravity there. This because you can't get the R.id.textinput_error_text id before having an error previous set.
Using Kotlin:
class TextInputLayoutErrorEnd(context: Context, attrs: AttributeSet) :
TextInputLayout(context, attrs) {
override fun setError(errorText: CharSequence?) {
super.setError(errorText)
errorText?.let {
val errorTextView = findViewById<TextView>(R.id.textinput_error_text)
errorTextView.gravity = Gravity.END
}
}
}
On your XML:
<package.TextInputLayoutErrorEnd...>
<com.google.android.material.textfield.TextInputEditText.../>
</package.TextInputLayoutErrorEnd>
How can i create an editText that looks like this?
You can do this using TextInputLayout and EditText.
Here is your XML:
<android.support.design.widget.TextInputLayout
android:id="#+id/text_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Label">
<EditText
android:id="#+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text" />
</android.support.design.widget.TextInputLayout>
1. Add attribute android:hint="Label" to TextInputLayout to show its hints Label always.
2. Programmatically set EditText hints Placeholder only when EditText get focused.
Add below lines in your Activity:
.........
.................
final EditText editText = (EditText) findViewById(R.id.edit_text);
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
editText.setHint("Placeholder");
} else {
editText.setHint("");
}
}
});
.........
..................
OUTPUT:
Hope this will help~
With the Material Components Library you can use:
app:placeholderText: to add a placeholder text in the EditText
android:hint: to add a floating label
They can work together:
<com.google.android.material.textfield.TextInputLayout
android:hint="Label"
app:placeholderText="Placeholder Text"
Note: it requires at least the version 1.2.0-alpha03.
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Label">
<android.support.design.widget.TextInputEditText
android:hint="Placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textEmailAddress" />
</android.support.design.widget.TextInputLayout>
Notice that android:hint="Placeholder" from TextInputEditText is visible at the same time with android:hint="Label" from TextInputLayout when view is not focused. You could do some extra checking in your java code to show and hide that label. Or just leave android:hint="Placeholder" from TextInputLayout.
To change color, you need to set a theme using android:theme="#style/TextLabel for TextInputLayout and there set your color accent.
<style name="TextLabel" parent="TextAppearance.AppCompat.Light">
<item name="colorAccent">#color/yourColor</item>
</style>
You can use following code (in kotlin). It will show placeholder after 200 ms delay (to avoid overlapping hint and placeholder).
class PlaceholderEditText : TextInputEditText {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
private val placeholder = hint
init {
hint = ""
onFocusChangeListener = OnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
postDelayed({ hint = placeholder }, 200)
} else {
hint = ""
}
}
}
}
and then in layout xml class:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="ALWAYS VISIBLE LABEL">
<com.myapp.widget.PlaceholderEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="DISAPPEARING PLACEHOLDER" />
</android.support.design.widget.TextInputLayout>
GIVEN: A TextInputEditText nested in TextInputLayout!
TL;DR!: Use this Kotlin Extension Function
fun EditText.setHintAndLabel(
textInputLayout: TextInputLayout,
label: String?, // hint in the TextInputLayout
hint: String? // hint in the EditText
) {
this.hint = ""
textInputLayout.hint = label
this.onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
this.hint = hint ?: ""
} else {
this.hint = ""
}
}
}
What's the problem and how does it solve it?
The Problem is that the hint of the EditText gets overlapped if there is a hint in the TextInputLayout. Which one to show in this case? Good question: We only want the EditText's hint to be displayed when it's focused/the cursor is inside but the TextInputLayout hint to be displayed always.
⮑ So we only set the hint for the EditText when it has the focus and remove it once it loses focus 🐙
As i know, best possible way how to solve this task with 2 different texts (placeholder and hint) together is to use the code below:
<com.google.android.material.textfield.TextInputLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:hintEnabled="true" // enable hint/placeholder on EditText
android:hint="#string/title_of_input" // title shown above EditText
app:expandedHintEnabled="false" // disable move placeholder to hint place
app:placeholderText="#string/placeholder_for_edittetx" // placeholder shown in EditText when no text is filled by user
>
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
You can use below layout xml file as below.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="Label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textView2"
android:textColor="#color/wallet_holo_blue_light" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="Name"
android:ems="10"
android:id="#+id/editText2"
android:hint="Placeholder" />
</LinearLayout>
If you use textinputlayout then on focus of edittext, you didn't get any placeholder.
Layout:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/username_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
You have to set a focus change listener of the edittext.
Java:
usernameTxt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
usernameTxt.setHint("Label");
} else {
usernameTxt.setHint("Placeholder");
}
}
});
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
}
}