org.strongswan.android.ui.view.TextInputLayoutHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.strongswan.android.ui.view.TextInputLayoutHelper.java

Source

/*
 * Copyright (C) 2016 Tobias Brunner
 * HSR Hochschule fuer Technik Rapperswil
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 */

package org.strongswan.android.ui.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

import org.strongswan.android.R;

/**
 * Layout that extends {@link android.support.design.widget.TextInputLayout} with a helper text
 * displayed below the text field when it receives the focus. Also, any error message shown with
 * {@link #setError(CharSequence)} is hidden when the text field is changed (this mirrors the
 * behavior of {@link android.widget.EditText}).
 */
public class TextInputLayoutHelper extends TextInputLayout {
    private LinearLayout mHelperContainer;
    private TextView mHelperText;

    public TextInputLayoutHelper(Context context) {
        this(context, null);
    }

    public TextInputLayoutHelper(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TextInputLayoutHelper(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextInputLayoutHelper);
        String helper = a.getString(R.styleable.TextInputLayoutHelper_helper_text);
        a.recycle();
        if (helper != null) {
            mHelperContainer = new LinearLayout(context);
            mHelperContainer.setOrientation(LinearLayout.HORIZONTAL);
            mHelperContainer.setVisibility(View.INVISIBLE);
            addView(mHelperContainer, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

            mHelperText = new TextView(context);
            mHelperText.setText(helper);
            mHelperText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
            a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.textColorSecondary });
            mHelperText.setTextColor(a.getColor(0, mHelperText.getCurrentTextColor()));
            a.recycle();

            mHelperContainer.addView(mHelperText, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        }
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
        if (child instanceof EditText) {
            EditText text = (EditText) child;
            text.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                }

                @Override
                public void afterTextChanged(Editable s) {
                    if (getError() != null) {
                        setError(null);
                    }
                }
            });
            if (mHelperContainer != null) {
                text.setOnFocusChangeListener(new OnFocusChangeListener() {
                    @Override
                    public void onFocusChange(View v, boolean hasFocus) {
                        showHelper(hasFocus);
                    }
                });
                ViewCompat.setPaddingRelative(mHelperContainer, ViewCompat.getPaddingStart(text), 0,
                        ViewCompat.getPaddingEnd(text), text.getPaddingBottom());
            }
        }
    }

    @Override
    public void setError(@Nullable CharSequence error) {
        super.setError(error);
        if (mHelperContainer != null) {
            if (error == null) { /* this frees up space used by the now invisible error message */
                setErrorEnabled(false);
            } else { /* re-add the helper as the error message should be displayed directly under the textbox */
                removeView(mHelperContainer);
                addView(mHelperContainer, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
            }
        }
    }

    /**
     * Set the helper text to be displayed below the text field.
     *
     * @attr ref R.styleable#TextInputLayoutHelper_helper_text
     */
    public void setHelperText(CharSequence text) {
        mHelperText.setText(text);
    }

    private void showHelper(boolean show) {
        if (show == (mHelperContainer.getVisibility() == View.VISIBLE)) {
            return;
        }
        if (show) {
            ViewCompat.animate(mHelperContainer).alpha(1f).setDuration(200)
                    .setListener(new ViewPropertyAnimatorListenerAdapter() {
                        @Override
                        public void onAnimationStart(View view) {
                            view.setVisibility(View.VISIBLE);
                        }
                    }).start();
        } else {
            ViewCompat.animate(mHelperContainer).alpha(0f).setDuration(200)
                    .setListener(new ViewPropertyAnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(View view) {
                            view.setVisibility(View.INVISIBLE);
                        }
                    }).start();
        }
    }
}