Передать ссылку на представление в CustomView - PullRequest
0 голосов
/ 03 февраля 2020

У меня есть один линейный макет, в котором у меня есть два представления для адреса электронной почты, одно - Textview, а другое - Edittext.

  1. Если есть пустой или неправильный адрес электронной почты, тогда цвет Textview должен измените на красный
  2. , если пользователь получает фокус на редактируемый текст. Цвет Textview должен измениться на синий.
  3. , если пользователь потерял фокус на EditText, тогда цвет TextView должен измениться на черный.

Чтобы проверить, как добиться этого с помощью customview, я создал настраиваемое представление его родительского представления LinearLayout, которое находится ниже

CustomLinearLayout. java file

public class CustomLinearLayout extends LinearLayout {


int editTextResourceId, textViewResourceId;
EditText editText;
TextView textView;
Context mContext;

public CustomLinearLayout(Context context) {
    super(context);
    mContext = context;
}

public CustomLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mContext = context;
    inflate(context, R.layout.activity_register_account_new, this);
    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyTextView, defStyleAttr, 0);
    editTextResourceId = a.getResourceId(R.styleable.MyTextView_supportedEditText, NO_ID);
    textViewResourceId = a.getResourceId(R.styleable.MyTextView_supportedTextView, NO_ID);
    a.recycle();

}

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    if (editTextResourceId != 0 && textViewResourceId != 0) {
        editText = (EditText)findViewById(editTextResourceId);
        editText.addTextChangedListener(new TextWatcher() {

            @Override
            public void afterTextChanged(Editable s) {}

            @Override
            public void beforeTextChanged(CharSequence s, int start,
                                          int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start,
                                      int before, int count) {
                if(s.length() != 0){
                    textView.setText(s);
                }
            }
        });
    }

}

}

activity_main. xml файл выглядит как

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/grey"
    android:orientation="vertical">

    <mobile.android.view.CustomLinearLayout
            style="@style/RegisterItem"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            custom:supportedEditText="@id/edUserName"
            custom:supportedTextView="@id/tvUserName"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/tvUserName"
                style="@style/RegisterTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/username" />

            <EditText
                android:id="@+id/edUserName"
                style="@style/RegisterEditText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:hint="@string/hint_username"
                android:inputType="textPersonName" />

        </mobile.android.view.CustomLinearLayout>

attris. xml file

 <declare-styleable name="MyTextView">
        <attr name="supportedEditText" />
        <attr name="supportedTextView" />
    </declare-styleable>

Но всякий раз, когда я отлаживаю код, он показывает мне 0 (идентификатор ресурса) вместо правильного идентификатора или NO_ID.

Может кто-нибудь помочь мне, как решить эту проблему? спасибо,

Ответы [ 2 ]

1 голос
/ 03 февраля 2020

Попробуйте этот код внутри CustomLinearLayout. java:

private EditText findEditText() {

    int i = 0;
    for (; i < getChildCount(); i++) {
        if (getChildAt(i) instanceof EditText) {
            return (EditText) getChildAt(i);
        }

    }
    return null;
}

private TextView findTextView() {

    int i = 0;
    for (; i < getChildCount(); i++) {
        if (getChildAt(i) instanceof TextView) {
            return (TextView) getChildAt(i);
        }

    }
    return null;
}

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    TextView textView = findTextView();
    EditText editText = findEditText();
    if (editText != null) {
        editText.addTextChangedListener(new TextWatcher() {

            @Override
            public void afterTextChanged(Editable s) {
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start,
                                          int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start,
                                      int before, int count) {
                if (s.length() != 0) {
                    if (textView != null) {
                        textView.setText(s);
                    }
                }
            }
        });
    }

}
0 голосов
/ 03 февраля 2020

Я создал одну вещь, как вы хотите, и я называю это: EditTextComponent Это java исходный код для EditTextComponent:

public class EdittextComponent extends InputComponent {

protected TextView tvTitle;
protected EditText edtInput;

protected int mInputType = InputType.TYPE_CLASS_TEXT;
protected int mMaxLine = 1;
protected InputFilter[] mInputFilter;
protected boolean hasFirstChange = false;
protected TextView tvWarning;

protected int mIDLayout = R.layout.component_edittext;
protected boolean isAlwaysShowWarning = false;

@Override
public View createView() {

    LayoutInflater inflater = LayoutInflater.from(mContext);
    rootView = inflater.inflate(mIDLayout, null, false);

    tvTitle = rootView.findViewById(R.id.tv_title);
    if (Utils.validateString(mTitle)) {
        tvTitle.setText(mTitle);
    }

    edtInput = rootView.findViewById(R.id.edt_input);

    if (Utils.validateString(mPlaceHolder)) {
        edtInput.setHint(mPlaceHolder);
    }

    edtInput.setInputType(mInputType);
    edtInput.setMaxLines(mMaxLine);
    if (null != mInputFilter && mInputFilter.length > 0) {
        edtInput.setFilters(mInputFilter);
    }

    if (Utils.validateString(mValue)) {
        edtInput.setText(mValue);
    }

    if(null != mValueSelected){
        isCompleted = true;
        String value = (String) mValueSelected;
        if(Utils.validateString(value)) {
            edtInput.setText(value);
        }
    }

    edtInput.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 (null != s) {
                hasFirstChange = true;
                checkChange(s.toString().trim());
            }
        }
    });

    tvWarning = rootView.findViewById(R.id.tv_warning);


    return rootView;
}

protected void checkChange(String source) {
    if (null != mValidator) {
        boolean newState = mValidator.validate(source);
        if (isCompleted != newState) {
            notifyStateChanged(newState, source);

        }
    } else {
        if (source.length() == 0) {
            if (isCompleted) {
                notifyStateChanged(false, source);
            }
        } else if (!isCompleted) {
            notifyStateChanged(true, source);
        }
    }

    if(isCompleted){
        edtInput.setBackgroundResource(R.drawable.bg_input);
        tvWarning.setVisibility(View.INVISIBLE);
    }
    else{
        showWarning(true);
    }

}

protected void notifyStateChanged(boolean is_complete, String source) {
    isCompleted = is_complete;
    if (null != mCallBack) {
        mCallBack.onChanged(isCompleted, source);
    }
}

public void updateValue(String value){
    mValue = value;
    if(null != edtInput){
        edtInput.setText(value);
    }
    checkChange(value);
}


@Override
public boolean validate() {

    if(!isVisible){
        return true;
    }

    if (!isCompleted ) {
            showWarning(false);
    }
    return isCompleted;
}

protected void showWarning(boolean isCallByItSelf) {
    String message = "Cannot be empty";
    if (null != mValidator) {
        message = mValidator.getMessage();
    }
    if(null != tvWarning) {
        tvWarning.setText(message);
        tvWarning.setVisibility(View.VISIBLE);
    }


    if(null != edtInput) {
        edtInput.setBackgroundResource(R.drawable.bg_input_warning);
    }
}

@Override
public String getValue() {
    mValue = edtInput.getText().toString();
    return mValue;
}

@Override
public Object getData() {
    return getValue();
}

public void setInputType(int inputType) {
    mInputType = inputType;
}

public void setMaxLine(int maxLine) {
    mMaxLine = maxLine;
}

public void setInputFilter(InputFilter[] inputFilter) {
    mInputFilter = inputFilter;
}

public void setIDLayout(int IDLayout) {
    mIDLayout = IDLayout;
}

public void setAlwaysShowWarning(boolean alwaysShowWarning) {
    isAlwaysShowWarning = alwaysShowWarning;
}}

А вот component_edittext. xml

<?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="match_parent">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginStart="10dp"
        android:layout_marginTop="5dp"
        android:layout_marginEnd="10dp"

        android:text="Last name"
        android:textColor="#333333"
        android:textSize="14sp"/>

    <EditText
        android:id="@+id/edt_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_title"
        android:layout_marginStart="10dp"
        android:layout_marginTop="9dp"
        android:layout_marginEnd="10dp"
        android:background="@drawable/bg_input_inactive"

        android:paddingStart="19dp"
        android:paddingTop="16dp"
        android:paddingBottom="15dp"
        android:textColor="#333333"
        android:textSize="14sp"/>

    <TextView
        android:id="@+id/tv_warning"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/edt_input"
        android:layout_alignParentEnd="true"
        android:layout_marginStart="10dp"
        android:layout_marginTop="5dp"
        android:layout_marginEnd="10dp"

        android:text="Cannot be empty"
        android:textColor="#DD4033"
        android:textSize="12sp"
        android:visibility="invisible"/>
</RelativeLayout>

InputComponent. java

public class InputComponent extends BaseComponent {
protected String mTitle;
protected String mValue;
protected String mKey;
protected String mPlaceHolder;
protected Validator mValidator;
protected boolean isCompleted = false;
protected InputCallBack mCallBack;
protected float mWeight = 1;

public boolean validate(){
    return false;
}

public String getTitle() {
    return mTitle;
}

public void setTitle(String title) {
    mTitle = title;
}

public String getValue() {
    return mValue;
}

public void setValue(String value) {
    mValue = value;
}

public String getKey() {
    return mKey;
}

public void setKey(String key) {
    mKey = key;
}

public void setCallBack(InputCallBack callBack) {
    mCallBack = callBack;
}

public void setPlaceHolder(String placeHolder) {
    mPlaceHolder = placeHolder;
}

public void setValidator(Validator validator) {
    mValidator = validator;
}

public float getWeight() {
    return mWeight;
}

public void setWeight(float weight) {
    mWeight = weight;
}

}

BaseComp onet. java

public class BaseComponent  implements Comparable<BaseComponent>{
protected View rootView;
protected String mIDComponent;
protected Context mContext;
protected Object mValueSelected;
protected int mPosition;
protected boolean isVisible = true;

public BaseComponent() {
    mContext = Manager.getInstance().getCurrentActivity();
}

public View createView() {
    return rootView;
}

public Object getValueSelected() {
    return mValueSelected;
}

public void setValueSelected(Object valueSelected) {
    mValueSelected = valueSelected;
}

public String getIDComponent() {
    return mIDComponent;
}

public void setIDComponent(String IDComponent) {
    mIDComponent = IDComponent;
}

public void setRootView(View rootView) {
    this.rootView = rootView;
}

public int getPosition() {
    return mPosition;
}

public void setPosition(int position) {
    mPosition = position;
}

public Object getData(){
    return  null;
}

public void removeAllView(){

}

public boolean isVisible() {
    return isVisible;
}

public void setVisible(boolean visible) {
    isVisible = visible;
}

public void updateView(){
    if(null != rootView){
        if(isVisible){
            rootView.setVisibility(View.VISIBLE);
        }
        else{
            rootView.setVisibility(View.GONE);
        }
    }
}

public View getRootView() {
    return rootView;
}

@Override
public int compareTo( BaseComponent otherComponent) {
    if (null != otherComponent) {
        return (otherComponent.getPosition() - getPosition());
    }
    return 0;
}

}

И это как вы можете использовать EditTextComponent:

        EdittextComponent lastNameComponent = new EdittextComponent();
        lastNameComponent.setPlaceHolder("Enter last name");
        lastNameComponent.setTitle("Last name");
        lastNameComponent.setKey("lastname");
        lastNameComponent.setCallBack(new InputCallBack() {
            @Override
            public void onChanged(boolean isSelected, Object data) {

                checkComplete();
            }
        });

        listInputComponents.add(lastNameComponent);

Вы можете использовать этот компонент для создания электронной почты, фамилии, телефонного кода .... и добавлять их в listInputComponents (массив). Затем вы можете добавить их в линейный вывод, например это:

    LinearLayout llBody = findViewById(...)
for(BaseComponent component: listInputComponents)
{ llBody.addView(component.createView()
}
...