본문 바로가기

Android

[Android] Collapse와 Expand 상태에서 힌트 문자가 다른 TextInputLayout

Collapsed 상태일 때와 Expanded 상태일 때 HInt가 다르게 표시되는 디자인 요청이 들어와서 커스텀 뷰로 제작해봤습니다.

동작에 문제가 생기면 업데이트 하겠습니다.

 

build.gradle

dependencies {
	...
    implemntation "com.google.android.material:material:$material_version"
    ...
}

SwitchTextInputLayout.java

import android.content.Context;
import android.content.res.TypedArray;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.material.textfield.TextInputLayout;

/**
 * Collapsed, Expanded 상태일 때 Hint 문구가 다른 TextInputLayout 입니다.
 *
 * <{package}.SwitchHintTextInputLayout
 *  android:layout_width="match_parent"
 *  android:layout_height="match_parent"
 *  app:hint_expanded="@string/hint_expanded"
 *  app:hint_collapsed="@string?hint_collapsed">
 *     <com.google.android.material.textfield.TextInputEditText
 *          android:layout_width="match_parent"
 *          android:layout_height="match_parent" />
 * </{package}.SwitchHintTextInputLayout>
 *
 * <p>
 * <p>
 * Copyright 2021 Junjae Bae
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
public class SwitchHintTextInputLayout extends TextInputLayout {

    private CharSequence mHintCollapsed;
    private CharSequence mHintExpanded;

    public SwitchHintTextInputLayout(@NonNull Context context) {
        this(context, null);
    }

    public SwitchHintTextInputLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, R.attr.textInputStyle);
    }

    public SwitchHintTextInputLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SwitchHintTextInputLayout, defStyleAttr, 0);
        mHintExpanded = a.getString(R.styleable.SwitchHintTextInputLayout_hint_expanded);
        mHintCollapsed = a.getString(R.styleable.SwitchHintTextInputLayout_hint_collapsed);

        a.recycle();
        if (TextUtils.isEmpty(mHintExpanded))
            mHintExpanded = getHint();
        else if (TextUtils.isEmpty(getHint())) {
            setHint(mHintExpanded);
        }

        if (TextUtils.isEmpty(mHintCollapsed)) {
            mHintCollapsed = getHint();
        }
    }

    @Override
    public void addView(View child, ViewGroup.LayoutParams params) {
        super.addView(child, params);
        if (child instanceof EditText) {
            EditText editChild = (EditText) child;

            updateHint();

            editChild.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) {
                    updateHint();
                }
            });
        }
    }

    @Override
    protected void drawableStateChanged() {
        updateHint();

        super.drawableStateChanged();
    }

    protected void updateHint() {
        final EditText editText = getEditText();
        if (editText != null) {
            final boolean isEnabled = isEnabled();

            final boolean hasText = editText != null && !TextUtils.isEmpty(editText.getText());
            final boolean hasFocus = editText != null && editText.hasFocus();

            if (isEnabled) {
                if (hasFocus || hasText) {
                    setHint(mHintCollapsed);
                } else {
                    setHint(mHintExpanded);
                }
            }
        }
    }

    public CharSequence getHintCollapsed() {
        return mHintCollapsed;
    }

    public void setHintCollapsed(CharSequence mHintCollapsed) {
        this.mHintCollapsed = mHintCollapsed;
        updateHint();
    }

    public CharSequence getHintExpanded() {
        return mHintExpanded;
    }

    public void setHintExpanded(CharSequence mHintExpanded) {
        this.mHintExpanded = mHintExpanded;
        updateHint();
    }
}

value/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="SwitchHintTextInputLayout">
        <attr name="hint_collapsed" format="string|reference"/>
        <attr name="hint_expanded" format="string|reference"/>
    </declare-styleable>
</resources>

 

마지막 업데이트 2021.2.18