将视图的引用传递给 CustomView

Pass reference of view to CustomView

我有一个线性布局,因为我有两个电子邮件地址视图,一个是 Textview,另一个是 Edittext。

  1. 当电子邮件地址为空或不正确时,Textview 的颜色应变为红色,
  2. 如果用户将焦点放在编辑文本上,Textview 的颜色应该变为蓝色。
  3. 如果用户失去对 EditText 的关注,那么 TextView 的颜色应该变为黑色。

为了检查如何使用自定义视图实现,我创建了其父视图的自定义视图,即下方的 LinearLayout

CustomLinearLayout.java 文件

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 文件

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

但是每当我调试代码时,它都会显示 0(资源 ID)而不是正确的 ID 或 NO_ID。

谁能帮我解决这个问题?谢谢,

我构建了一个你想要的东西,我称之为:EditTextComponent 这是 EditTextComponent 的 java 源代码:

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

}

BaseComponet.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(数组) 然后你可以像这样将它们添加到 linearlaylout 中:

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

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

}