How to set the error text alignment to center in TextInputLayout - android

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>

Related

How to add TextInputLayout inside the LinearLayout by dynamically?

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);

ScrollView doesn't stretch enough

I have a LinearLayout(horizontal) inside a ScrollView. I'm trying to add TextView's and Button's inside LinearLayout with programmatically.
My code works without errors but with little glitch. My ScrollView only stretch for TextView not for Button's. Sorry for the inadequate explanation, maybe screenshot helps: Imgur.
❒ Eve gir. is a Button the rest is TextView.
How can I make ScrollView stretch and wrap my Button's too. i tried set the fillViewPort but it did not work.
TextView adding code:
private fun createText(prTx: String, color: String) {
val text = TextView(this)
text.text = prTx
text.gravity = Gravity.CENTER_HORIZONTAL
text.textSize = 18F
text.setShadowLayer(5F,3F,2F,Color.BLACK)
when (color) {
"n" -> text.setTextColor(Color.WHITE)
"p" -> text.setTextColor(Color.rgb(255,182,193))
"m" -> text.setTextColor(Color.rgb(182,207,255))
"cm" -> text.setTextColor(Color.rgb(182, 242, 227))
"olay" -> {
text.setShadowLayer(5F,3F,2F,Color.rgb(100,0,166))
text.setTextColor(Color.rgb(75,0,130))
}
}
text.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
text.layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
val layout = findViewById<LinearLayout>(R.id.llText)
layout.addView(text)
}
Button adding code
private fun createButton(prTx: String, clk: Int) {
val button = Button(this)
button.text = prTx
button.setBackgroundColor(Color.TRANSPARENT)
button.gravity = Gravity.CENTER_HORIZONTAL;
button.textSize = 18F
button.transformationMethod = null;
button.setTextColor(Color.WHITE)
button.setShadowLayer(10F,5F,5F, Color.BLACK)
button.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
button.setOnClickListener {
when (clk) {
}
}
button.layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
val layout = findViewById<LinearLayout>(R.id.llText)
layout.addView(button)
}
Layout's XML codes
<ScrollView
android:id="#+id/sv"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="#5B34515E"
android:fadeScrollbars="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/ivMutfak"
app:layout_constraintHeight_default="wrap"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="#+id/clMiddle"
app:layout_constraintTop_toBottomOf="#+id/clMiddle"
app:layout_constraintVertical_bias="0.0">
<LinearLayout
android:id="#+id/llText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:orientation="vertical" />
</ScrollView>
The problem was not ScrollView, it was LinearLayout. Problem solved when I deleted it android:layout_margin's of `LinearLayout. I still don't know why but this solution worked for me.
You should use LinearLayout.LayoutParams.WRAP_CONTENT instead of ViewGroup.LayoutParams.MATCH_PARENT. Try this code
LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT)

Kotlin Custom View referencing textview returns null

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"
}
}

Disable EditText OnTouchListener or OnClickListener in custom view

I have a custom View which contains a LinearLayout in turn containing a TextView and and an EditText. When I will try to click on my custom view if I have pressed on the TextView the LinearLayout will receive the click but if I have pressed on the EditText it will not.
Below is a simplified version of my xml.
<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/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="#+id/edt_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="#color/md_green_800" />
</LinearLayout>
So when I will press on the EditText I want the parent view (the LinearLayout) to receive the click.
I have tried below code:
private void init(Context context, AttributeSet attrs) {
LayoutInflater inflater = LayoutInflater.from(context);
binding = LayoutHeadingEdittextBinding.inflate(inflater, this, true);
TypedArray array = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.headingtext,
0, 0);
if (attrs != null) {
try {
String hint = array.getString(R.styleable.headingtext_field_hint);
String name = array.getString(R.styleable.headingtext_field_name);
String text = array.getString(R.styleable.headingtext_field_text);
Boolean isFocuable = array.getBoolean(R.styleable.headingtext_field_focus, true);
if (!isFocuable) {
binding.edtTitle.setClickable(false);
binding.edtTitle.setFocusable(false);
binding.edtTitle.setFocusableInTouchMode(false);
binding.edtTitle.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
((View) v.getParent()).performClick();
}
});
// binding.edtTitle.setEnabled(false);
} else {
binding.edtTitle.setClickable(true);
binding.edtTitle.setFocusable(true);
binding.edtTitle.setFocusableInTouchMode(true);
}
binding.edtTitle.setHint(hint);
binding.tvTitle.setText(name);
binding.edtTitle.setText(text);
} finally {
array.recycle();
}
}
}
And this is how i want to use it:
<packagename.customView.HeadingEditText
android:id="#+id/edt_country"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="#string/mobile_or_wechat"
android:onClick="#{()->frag.onCountryClick(countryList)}"
app:field_focus="false"
app:field_hint="#string/country"
app:field_name="#string/country"
app:field_text='#{basicinfo.country_name!=null?basicinfo.country_name:""}'
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/edt_address" />
But it is still not working So i think issue with databinding and click of my customview.
Programatically
//disable click action
editText.setFocusable(false);
editText.setEnabled(false);
//enable click action
editText.setFocusable(true);
editText.setEnabled(true);
xml:
android:focusable="false"
android:enabled="false"
Try this in EditText :
android:focusable="true"
android:focusableInTouchMode="true"
Programatically :
editText.setFocusable(false);
===============EDIT===============
if (!isFocuable) {
binding.edtTitle.setClickable(false);
binding.edtTitle.setFocusable(false);
binding.edtTitle.setFocusableInTouchMode(false);
binding.edtTitle.setOnTouchListener(null);
binding.edtTitle.setOnClickListener(null);
// binding.edtTitle.setEnabled(false);
} else {
binding.edtTitle.setClickable(true);
binding.edtTitle.setFocusable(true);
binding.edtTitle.setFocusableInTouchMode(true);
binding.edtTitle.setOnTouchListener(this);
binding.edtTitle.setOnClickListener(this);
}
===============EDIT===============
Add in edittext
android:duplicateParentState="true"
If this not works then try with this line also
android:duplicateParentState="true"
android:clickable="false"
Here is a work around.
// Inside HeadingEditText.kt
binding.edtTitle.setOnClickListener {
this#HeadingEditText.performClick()
}
Set the OnClickListener at your Activity
edt_country.edtTitle.setOnClickListener {
// foo action
}
THIS IS NOT A GOOD SOLUTION
JUST USABLE IN A CUSTOM-VIEW USING A FrameLayout
on your parent (ViewGroup) of contained EditText, override onInterceptTouchEvent method like this:
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return true
}
I use EditText inside a FrameLayout and override the method inside my FrameLayout and all of them used inside a recycler list item (xml)... and Worked fine click listener of recycler root item view...

Android EditText with different floating label and placeholder

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");
}
}
});

Categories

Resources