Baseline aligned TextInputLayout and Spinner - android

I try to align spinner and edit text by baseline, but it doesn't work:
It start happen after update support library dependency from 24.1.1 to 24.2.1 (support-v4, appcompat-v7, design).
This is my xml code:
<RelativeLayout
android:id="#+id/email_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v7.widget.AppCompatSpinner
android:id="#+id/spinner"
style="#style/MailSpinner"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:dropDownWidth="wrap_content" />
<android.support.design.widget.TextInputLayout
android:id="#+id/text_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_alignBaseline="#id/spinner"
android:layout_toStartOf="#id/spinner"
android:baselineAlignedChildIndex="0">
<android.support.v7.widget.AppCompatEditText
android:id="#+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="E-mail"
android:ellipsize="end"
android:imeOptions="actionNext"
android:inputType="textEmailAddress"
android:textSize="16sp"/>
</android.support.design.widget.TextInputLayout>
</RelativeLayout>
MailSpinner style:
<style name="MailSpinner" parent="Widget.AppCompat.Spinner.Underlined">
<item name="android:background">#drawable/spinner_textfield_background</item>
<item name="backgroundTint">#color/spinner_tint</item>
<item name="backgroundTintMode">src_atop</item>
</style>

Essentially the TextInputLayout isn't providing a baseline value to it's parent. We need to pipe the correct baseline of the EditText by extending TextInputLayout. This works for me, however, I'm not sure if the baseline would change due to other events from the TextInputLayout.
public class CTextInputLayout extends TextInputLayout {
public CTextInputLayout(Context context) {
super(context);
}
public CTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public int getBaseline()
{
EditText editText = getEditText();
return editText.getPaddingTop() + editText.getBaseline();
}
}

I think this version is better when hint label is floating
public class CTextInputLayout extends TextInputLayout {
public CTextInputLayout(Context context) {
super(context);
}
public CTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public int getBaseline() {
EditText editText = getEditText();
return getMeasuredHeight() - (editText.getMeasuredHeight() - editText.getBaseline());
}
}

Here's a version which aligns correctly when the TextInputLayout error text is set:
public class BaselineTextInputLayout extends TextInputLayout {
public BaselineTextInputLayout(Context context) {
super(context);
}
public BaselineTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BaselineTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public int getBaseline() {
EditText editText = getEditText();
if (editText == null) { return 0; }
return editText.getTop() + editText.getBaseline();
}
}

Related

Android: style not applied to a button

In styles.xml I got:
<style name="MyButtonStyle">
<item name="android:buttonStyle">#style/Base.Widget.AppCompat.Button.Borderless</item>
<item name="android:textSize">24px</item>
<item name="android:drawablePadding">4dp</item>
<item name="android:textColor">#color/menuButtonForecolor</item>
<item name="android:textStyle">bold</item>
</style>
I wanna use this style inside CMyButton.java like this
public class CMyButton extends AppCompatButton {
private static int getDefStyleId()
{
return R.style.MyButtonStyle;
}
protected void initThis() {
}
public CMyButton(Context context) {
this(context,null, getDefStyleId());
}
public CMyButton(Context context, AttributeSet attrs) {
this(context, attrs, getDefStyleId());
}
public CMyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.initThis();
}
}
I use this button in panel_layout.xml:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/LinearLayoutTheme">
<college.test.progs.CMyButton
android:id="#+id/showFacultiesButton"
android:text="#string/faculties_button_title"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</merge>
And this panel_layout.xml is used inside CPanel.java
public class CPanel extends LinearLayout {
private CMyButton facultiesButton;
protected void initThis(Context context) {
inflate(getContext(),R.layout.panel_layout,this);
this.facultiesButton = (CMyButton) findViewById(R.id.showFacultiesButton);
}
public CPanel(Context context) {
this(context,null);
}
public CPanel(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CPanel(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.initThis(context);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CPanel(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
this.initThis(context);
}
}
Then I add this panel layout to main activity's layout
But when I add this button to any activity the style is not applied. What is wrong with this class? I know that I can apply the style in layout file but I need to do it in the code
Did you change MyButtonStyle as your theme's android:buttonStyle attribute value?
Hope this helps!
There are 2 ways to apply a style to a view:
Apply it directly to the view:
<college.test.progs.CMyButton
android:id="#+id/showFacultiesButton"
android:text="#string/faculties_button_title"
android:gravity="center"
android:style="#style/MyButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Apply it to the Application through the style.xml file:
<item name="buttonStyle">#style/MyButtonStyle</item>

What is correct way to make custom view based on EditText?

What is correct way to extend EditText?
The problem is following:
I have empty application from template with two EditText:
<?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="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="one"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="two"/>
</LinearLayout>
It works fine:
Then I create my custom view from EditText:
public class CuteEditText extends EditText {
public CuteEditText(Context context) {
this(context, null);
}
public CuteEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CuteEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// some special initialization will be here
}
}
And when I change EditText to my CuteEditText, interface works incorrectly:
The problem is not only with view ot UI. If I type something in first EditText and than touch the second one, nohing happens: input will continue in first.
The same behaviour if I inherite CuteEditText from AppCompatEditText.
What is wrong?
Sources for experiment are available at https://github.com/tseglevskiy/EditTextExperiment
Your construtors are broken. This is how it should look:
public class CuteEditText extends EditText {
public CuteEditText(Context context) {
super(context);
}
public CuteEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CuteEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
You don't need the third constructor overload. The first one is for creating the view programmatically and the second one is for creating the view from xml. Those two should be enough for most cases.
public class CuteEditText extends EditText {
public CuteEditText(Context context) {
this(context, null);
}
public CuteEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
}

Android custom AutoCompleteTextView doesn't appear after hiding

I create an autoCompleteTextView as below Layout and Java class :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/autoCompleteTextViewGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:minHeight="#dimen/component_height">
<android.support.design.widget.TextInputLayout
android:id="#+id/textInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:animateLayoutChanges="true">
<AutoCompleteTextView
android:id="#+id/autoCompleteTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<android.support.v4.widget.ContentLoadingProgressBar
android:id="#+id/progressBar"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:indeterminate="true"
android:indeterminateDrawable="#anim/anim_indeterminate_mini"
android:interpolator="#anim/anim_progress_interpolator"
android:visibility="visible" />
</FrameLayout>
and Java class is :
public class MAutoCompleteText extends LinearLayout {
AutoCompleteTextView autoCompleteTextView;
ContentLoadingProgressBar progressBar;
TextInputLayout textInputLayout;
ViewGroup autoCompleteTextViewGroup;
public MAutoCompleteText(Context context) {
super(context);
init(context);
}
public MAutoCompleteText(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MAutoCompleteText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
#TargetApi(21)
public MAutoCompleteText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context) {
inflate(context, R.layout.layout_auto_complete_text, this);
autoCompleteTextViewGroup = (ViewGroup) findViewById(R.id.autoCompleteTextViewGroup);
textInputLayout = (TextInputLayout) findViewById(R.id.textInputLayout);
autoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView);
progressBar = (ContentLoadingProgressBar) findViewById(R.id.progressBar);
}
public void setAdapter(ArrayAdapter<String> adapter) {
autoCompleteTextView.setAdapter(adapter);
}
public String getText() {
return autoCompleteTextView.getText().toString();
}
public void setErrorEnabled(boolean status) {
textInputLayout.setErrorEnabled(status);
}
public void setError(int errorId) {
textInputLayout.setError(getContext().getString(errorId));
}
public int getVisibility() {
return autoCompleteTextViewGroup.getVisibility();
}
public void setVisibility(int visibility) {
autoCompleteTextViewGroup.setVisibility(visibility);
autoCompleteTextViewGroup.setMinimumHeight(R.dimen.component_height);
}
public void setProgressBarVisibility(int visibility) {
progressBar.setVisibility(visibility);
}
public MAutoCompleteText setHint(int hintId) {
autoCompleteTextView.setHint(hintId);
return this;
}
public void setImeOption(int imeOption) {
autoCompleteTextView.setImeOptions(imeOption);
}
}
Everything work OK. I setVisibility(GONE) and my component hide from UI,
but when I use setVisibility(VISIBLE) doesn't happen any thing !!!!
How can I display my component programmatically?
I found answer of my problem , at least it works now ... :)
I change setVisibility to below code :
public void setVisibility(int visibility) {
autoCompleteTextViewGroup.setVisibility(visibility);
if (visibility == View.VISIBLE) {
textInputLayout.setVisibility(visibility);
autoCompleteTextView.setVisibility(visibility);
progressBar.setVisibility(visibility);
requestLayout();
}
}
In fact requestLayout(); reDraw layout of my component on UI again and it`s appear correctly .

textView.setText is not working in compound view

textView.setText is not working properly in a compound view.
Means Both hello and jack are appearing...
and jack is displayed below layout not appearing if I put some background color,...
Could somebody help... Thanks and regards...
Here is my code...
Layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/chatLayout"
android:layout_width="300dp"
android:layout_height="400dp"
>
<TextView
android:id="#+id/chatNamed"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Hello"
android:textColor="#ffffff"
android:textSize="20dp"
android:textStyle="bold"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
/>
</RelativeLayout>
CompoundView.java
public class ChatCompoundView extends RelativeLayout {
private static TextView zoneName;
public ChatCompoundView(Context context) {
this(context, null);
setView();
}
public ChatCompoundView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
setView();
}
public ChatCompoundView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setView();
}
public void setView()
{
inflate(getContext(), R.layout.chat_layout, this);
zoneName = (TextView) findViewById(R.id.chatNamed);
}
zoneName.setText("jack");
}
try this..
LayoutInflater mInflater;
public ChatCompoundView (Context context) {
super(context);
mInflater = LayoutInflater.from(context);
setView();
}
setView():
public void setView(){
mInflater.inflate(R.layout.custom_view, this, true);
TextView zoneName = (TextView) findViewById(R.id.chatNamed);
zoneName .setText("jack");
}
Yeah Now I got the Answer... Actually my constructors are called with this(context),.. and I need to call super(context)...
Code Changed to
public ChatCompoundView(Context context) {
super(context);
setView();
}
public ChatCompoundView(Context context, AttributeSet attrs) {
super(context, attrs);
setView();
}
public ChatCompoundView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setView();
}

Define a Custom EditText

I'm a beginner. I want to define the xml for a custom EditText and then programmatically add those custom edittexts at runtime without using a bunch of code to customize the editTexts. This could be similar to implementing custom buttons, textviews, etc. from libraries...although it would be my own. What is the best way to approach this?
Thanks!
Alternative code apart from code shared in above comment link is below :
basically this code makes easy for user to customize the fonts etc.
public class MyEditText extends EditText {
public MyEditText(Context context) {
super(context);
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
parseAttributes(context, attrs);
}
public MyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
parseAttributes(context, attrs);
}
private void parseAttributes(Context context, AttributeSet attrs) {
TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.Simplified);
int typefaceValue = values.getInt(R.styleable.Simplified_typeface, 0);
values.recycle();
setTypeface(MyFontUtil.obtaintTypeface(context, typefaceValue));
}
}
XML
<com.my.mtetno.widget.MyEditText
android:id="#+id/uname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#drawable/lh_edit_field_without_border"
android:inputType="textEmailAddress"
android:maxLines="1"
android:overScrollMode="always"
android:textSize="#dimen/login_page_edit_text_size"
app:typeface="simplified_regular" />

Categories

Resources