美文网首页
Android 自定义编辑控件

Android 自定义编辑控件

作者: 周南城 | 来源:发表于2017-11-09 13:48 被阅读36次

    自定义编辑控件

    最近工作不太忙,对于之前像那种个人中心的编辑页面,以前的做法要么是使用RecyclerView,要么是一行一行的画,这次我突发奇想,想着整个项目里,这种地方还是挺多的,就干脆自定义一个算了,每次一行就是一个这个控件得了

    需求

    类似以下这种界面,太多了,但总归是首先分为

    • 有没有二级页面
    • 内容靠左还是靠右
    • 内容是用EditText还是TextView
    image
    image
    image

    实现

    EditLayout

    public class EditLayout extends RelativeLayout {
    
    private Context mContext;
    
    private TextView mTvTxtTag;//item的名称
    private FrameLayout mFlContent;//显示的内容
    private ImageView mIvNext;//下一页图标
    
    private int mTagColor;//tag的颜色
    private int mHintColor;//hint值的颜色
    private int mContentColor;//内容的颜色
    
    private int mTagSize;//tag的size
    private int mContentSize;//内容的size
    
    private boolean mIsHasNextPage;//是否有二级页面
    
    private String mTagTxt;//tag的文字内容
    private String mContentTxt;//Content的文字内容
    private String mHintTxt;//hint的文字内容
    
    private int mLines;//行数
    private int mMaxLines;//最大行数
    
    private TextUtils.TruncateAt mEllipsize;//折叠方式
    private static final int ELLIPSIZE_START = 0;
    private static final int ELLIPSIZE_MIDDLE = 1;
    private static final int ELLIPSIZE_END = 2;
    private static final int ELLIPSIZE_MARQUEE = 3;
    
    private static final int DEFAULT_LINE = 1;//默认输入一行
    
    private CONTENT_WIDGET mContentWidget;//内容的控件
    private static final int CONTENT_EDIT = 0;
    private static final int CONTENT_TEXT = 1;
    
    private int mContentGravity;//内容的填充方式
    private static final int CONTENT_GRAVITY_LEFT = -1;
    private static final int CONTENT_GRAVITY_CENTER = 0;
    private static final int CONTENT_GRAVITY_RIGHT = 1;
    
    private onEditLayoutEventLisenter mLisenter;//监听
    
    private int DEFAULT_TAG_SIZE = 48;//默认字体大小
    private int DEFAULT_CONTENT_SIZE = 48;//默认字体大小
    
    private EditText etContent;//输入框控件
    private TextView tvContent;//文本控件
    
    private int mInputType;//输入类型
    
    private int mContentMarginLeft;//内容距离左边的距离
    
    private static final int INPUT_TYPE_NUMBER = 0;
    private static final int INPUT_TYPE_TEXT = 1;
    private static final int INPUT_TYPE_DATE = 2;
    private static final int INPUT_TYPE_DATETIME = 3;
    private static final int INPUT_TYPE_NUMBERDECIMAL = 4;
    private static final int INPUT_TYPE_NUMBERPASSWORD = 5;
    private static final int INPUT_TYPE_NUMBERSIGNED = 6;
    private static final int INPUT_TYPE_PHONE = 7;
    private static final int INPUT_TYPE_TEXTAUTOCOMPLETE = 8;
    private static final int INPUT_TYPE_TEXTAUTOCORRECT = 9;
    private static final int INPUT_TYPE_TEXTEMAILADDRESS = 10;
    private static final int INPUT_TYPE_TEXTFILTER = 11;
    private static final int INPUT_TYPE_TEXTPASSWORD = 12;
    private static final int INPUT_TYPE_TEXTPERSONNAME = 13;
    private static final int INPUT_TYPE_TEXTURI = 14;
    private static final int INPUT_TYPE_TEXTVISIBLEPASSWORD = 15;
    
    private final AutoLayoutHelper mHelper = new AutoLayoutHelper(this);
    
    //内容的控件:EditText或者TextView
    protected enum CONTENT_WIDGET {
        EDITTEXT, TEXTVIEW
    }
    
    public EditLayout(Context context) {
        this(context, null);
    }
    
    public EditLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    
    public EditLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    
        mContext = context;
    
        initAttr(attrs);
        initView();
    }
    
    public int getContentGravity() {
        return mContentGravity;
    }
    
    public EditLayout setContentGravity(int contentGravity) {
        mContentGravity = contentGravity;
        if (etContent != null) {
            etContent.setGravity(contentGravity);
        }
        if (tvContent != null) {
            tvContent.setGravity(contentGravity);
        }
        return this;
    }
    
    public CONTENT_WIDGET getContentWidget() {
        return mContentWidget;
    }
    
    public EditLayout setContentWidget(CONTENT_WIDGET contentWidget) {
        mContentWidget = contentWidget;
        return this;
    }
    
    public EditLayout setContentTxt(String contentTxt) {
        mContentTxt = contentTxt;
        if (etContent != null) {
            etContent.setText(mContentTxt);
        }
        if (tvContent != null) {
            tvContent.setText(mContentTxt);
        }
        return this;
    }
    
    public int getInputType() {
        return mInputType;
    }
    
    public EditLayout setInputType(int inputType) {
        mInputType = inputType;
        if (etContent != null) {
            etContent.setInputType(inputType);
        }
        return this;
    }
    
    public int getTagColor() {
        return mTagColor;
    }
    
    public EditLayout setTagColor(int tagColor) {
        mTagColor = tagColor;
        if (mTvTxtTag != null) {
            mTvTxtTag.setTextColor(tagColor);
        }
        return this;
    }
    
    public int getHintColor() {
        return mHintColor;
    }
    
    public EditLayout setHintColor(int hintColor) {
        mHintColor = hintColor;
        if (etContent != null) {
            etContent.setHintTextColor(hintColor);
        }
        if (tvContent != null) {
            tvContent.setHintTextColor(hintColor);
        }
        return this;
    }
    
    public int getContentColor() {
        return mContentColor;
    }
    
    public EditLayout setContentColor(int contentColor) {
        mContentColor = contentColor;
        if (etContent != null) {
            etContent.setTextColor(contentColor);
        }
        if (tvContent != null) {
            tvContent.setTextColor(contentColor);
        }
        return this;
    }
    
    public int getTagSize() {
        return mTagSize;
    }
    
    public EditLayout setTagSize(int tagSize) {
        mTagSize = tagSize;
        if (mTvTxtTag != null) {
            mTvTxtTag.setTextSize(mTagSize);
        }
        return this;
    }
    
    public int getContentSize() {
        return mContentSize;
    }
    
    public EditLayout setContentSize(int contentSize) {
        mContentSize = contentSize;
        if (etContent != null) {
            etContent.setTextSize(mContentSize);
        }
        if (tvContent != null) {
            tvContent.setTextSize(mContentSize);
        }
        return this;
    }
    
    public boolean isHasNextPage() {
        return mIsHasNextPage;
    }
    
    public EditLayout setHasNextPage(boolean hasNextPage) {
        mIsHasNextPage = hasNextPage;
        if (mIsHasNextPage) {
            if (mIvNext != null)
                mIvNext.setVisibility(VISIBLE);
        } else {
            if (mIvNext != null)
                mIvNext.setVisibility(INVISIBLE);
        }
        return this;
    }
    
    public String getTagTxt() {
        return mTagTxt;
    }
    
    public EditLayout setTagTxt(String tagTxt) {
        mTagTxt = tagTxt;
        if (mTvTxtTag != null) {
            mTvTxtTag.setText(tagTxt);
        }
        return this;
    }
    
    public String getContentTxt() {
        return mContentTxt;
    }
    
    public String getHintTxt() {
        return mHintTxt;
    }
    
    public EditLayout setHintTxt(String hintTxt) {
        mHintTxt = hintTxt;
        if (etContent != null) {
            etContent.setHint(mHintTxt);
        }
        if (tvContent != null) {
            tvContent.setHint(mHintTxt);
        }
        return this;
    }
    
    public int getContentMarginLeft() {
        return mContentMarginLeft;
    }
    
    public EditLayout setContentMarginLeft(int contentMarginLeft) {
        mContentMarginLeft = contentMarginLeft;
        if (mFlContent != null) {
            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mFlContent.getLayoutParams();
            lp.setMargins(contentMarginLeft, 0, 0, 0);
            mFlContent.setLayoutParams(lp);
        }
        return this;
    }
    
    /**
     * 初始化属性
     *
     * @param attrs
     */
    private void initAttr(AttributeSet attrs) {
    
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.EditLayout);
    
        mTagColor = typedArray.getColor(R.styleable.EditLayout_tag_color, getResources().getColor(R.color.default_black));
        mHintColor = typedArray.getColor(R.styleable.EditLayout_hint_color, getResources().getColor(R.color.default_gray_light));
        mContentColor = typedArray.getColor(R.styleable.EditLayout_content_color, getResources().getColor(R.color.default_black));
    
        mTagSize = typedArray.getDimensionPixelSize(R.styleable.EditLayout_tag_size, DEFAULT_TAG_SIZE);
        mContentSize = typedArray.getDimensionPixelSize(R.styleable.EditLayout_content_size, DEFAULT_CONTENT_SIZE);
    
        mIsHasNextPage = typedArray.getBoolean(R.styleable.EditLayout_has_next_page, false);
    
        mTagTxt = typedArray.getString(R.styleable.EditLayout_tag_txt);
        mContentTxt = typedArray.getString(R.styleable.EditLayout_content_txt);
        mHintTxt = typedArray.getString(R.styleable.EditLayout_hint_txt);
    
        mLines = typedArray.getInt(R.styleable.EditLayout_lines, DEFAULT_LINE);
        mMaxLines = typedArray.getInt(R.styleable.EditLayout_max_line, DEFAULT_LINE);
        int ellipsize = typedArray.getInt(R.styleable.EditLayout_ellipsize, ELLIPSIZE_END);
        if (ellipsize == ELLIPSIZE_START) {
            mEllipsize = TextUtils.TruncateAt.START;
        } else if (ellipsize == ELLIPSIZE_MIDDLE) {
            mEllipsize = TextUtils.TruncateAt.MIDDLE;
        } else if (ellipsize == ELLIPSIZE_END) {
            mEllipsize = TextUtils.TruncateAt.END;
        } else if (ellipsize == ELLIPSIZE_END) {
            mEllipsize = TextUtils.TruncateAt.MARQUEE;
        }
    
        int widgetType = typedArray.getInt(R.styleable.EditLayout_content_widget, CONTENT_EDIT);
        if (widgetType == CONTENT_EDIT) {
            mContentWidget = CONTENT_WIDGET.EDITTEXT;
        } else if (widgetType == CONTENT_TEXT) {
            mContentWidget = CONTENT_WIDGET.TEXTVIEW;
        }
    
        int contentGravity = typedArray.getInt(R.styleable.EditLayout_content_gravity, CONTENT_GRAVITY_LEFT);
        if (contentGravity == CONTENT_GRAVITY_LEFT) {
            mContentGravity = Gravity.LEFT;
        } else if (contentGravity == CONTENT_GRAVITY_CENTER) {
            mContentGravity = Gravity.CENTER;
        } else if (contentGravity == CONTENT_GRAVITY_RIGHT) {
            mContentGravity = Gravity.RIGHT;
        }
    
        int inputType = typedArray.getInt(R.styleable.EditLayout_input_type, InputType.TYPE_CLASS_TEXT);
        if (inputType == INPUT_TYPE_NUMBER) {//number
            mInputType = InputType.TYPE_CLASS_NUMBER;
        } else if (inputType == INPUT_TYPE_TEXT) {//text
            mInputType = InputType.TYPE_CLASS_TEXT;
        } else if (inputType == INPUT_TYPE_DATE) {//date
            mInputType = InputType.TYPE_DATETIME_VARIATION_DATE;
        } else if (inputType == INPUT_TYPE_DATETIME) {//datetime
            mInputType = InputType.TYPE_CLASS_DATETIME;
        } else if (inputType == INPUT_TYPE_NUMBERDECIMAL) {//numberDecimal
            mInputType = InputType.TYPE_NUMBER_FLAG_DECIMAL;
        } else if (inputType == INPUT_TYPE_NUMBERPASSWORD) {//numberPassword
            mInputType = InputType.TYPE_NUMBER_VARIATION_PASSWORD;
        } else if (inputType == INPUT_TYPE_NUMBERSIGNED) {//numberSigned
            mInputType = InputType.TYPE_NUMBER_FLAG_SIGNED;
        } else if (inputType == INPUT_TYPE_PHONE) {//phone
            mInputType = InputType.TYPE_CLASS_PHONE;
        } else if (inputType == INPUT_TYPE_TEXTAUTOCOMPLETE) {//textAutoComplete
            mInputType = InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE;
        } else if (inputType == INPUT_TYPE_TEXTAUTOCORRECT) {//textAutoCorrect
            mInputType = InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
        } else if (inputType == INPUT_TYPE_TEXTEMAILADDRESS) {//textEmailAddress
            mInputType = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
        } else if (inputType == INPUT_TYPE_TEXTFILTER) {//textFilter
            mInputType = InputType.TYPE_TEXT_VARIATION_FILTER;
        } else if (inputType == INPUT_TYPE_TEXTPASSWORD) {//textPassword
            mInputType = InputType.TYPE_TEXT_VARIATION_PASSWORD;
        } else if (inputType == INPUT_TYPE_TEXTPERSONNAME) {//textPersonName
            mInputType = InputType.TYPE_TEXT_VARIATION_PERSON_NAME;
        } else if (inputType == INPUT_TYPE_TEXTURI) {//textUri
            mInputType = InputType.TYPE_TEXT_VARIATION_URI;
        } else if (inputType == INPUT_TYPE_TEXTVISIBLEPASSWORD) {//textVisiblePassword
            mInputType = InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
        }
    
        typedArray.recycle();
    }
    
    /**
     * 初始化布局
     */
    private void initView() {
        View view = View.inflate(getContext(), R.layout.lay_edit_layout, this);
    
        mTvTxtTag = view.findViewById(R.id.tv_txt_tag);
        mFlContent = view.findViewById(R.id.fl_content);
        mIvNext = view.findViewById(R.id.iv_next);
    
        //tag的初始化
        mTvTxtTag.setText(mTagTxt);
        mTvTxtTag.setTextColor(mTagColor);
        mTvTxtTag.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTagSize);
        AutoUtils.autoTextSize(mTvTxtTag);
    
        //内容的组件的初始化
        if (mContentWidget == CONTENT_WIDGET.EDITTEXT) {
            etContent = new EditText(mContext);
    
            etContent.setInputType(mInputType);
            etContent.setLines(mLines);
            etContent.setMaxLines(mMaxLines);
            etContent.setEllipsize(mEllipsize);
            etContent.setText(mContentTxt);
            etContent.setTextColor(mContentColor);
            etContent.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContentSize);
    
            etContent.setBackgroundDrawable(null);
            etContent.setPadding(0, 0, 0, 0);
    
            etContent.setHint(mHintTxt);
            etContent.setHintTextColor(mHintColor);
    
            etContent.setGravity(mContentGravity | Gravity.CENTER_VERTICAL);
    
            mFlContent.removeAllViews();
            mFlContent.addView(etContent);
    
            AutoUtils.autoTextSize(etContent);
    
        } else if (mContentWidget == CONTENT_WIDGET.TEXTVIEW) {
            tvContent = new TextView(mContext);
    
            tvContent.setInputType(mInputType);
            tvContent.setLines(mLines);
            tvContent.setMaxLines(mMaxLines);
            tvContent.setEllipsize(mEllipsize);
            tvContent.setText(mContentTxt);
            tvContent.setTextColor(mContentColor);
            tvContent.setTextSize(TypedValue.COMPLEX_UNIT_PX, mContentSize);
    
            tvContent.setHint(mHintTxt);
            tvContent.setHintTextColor(mHintColor);
    
            tvContent.setGravity(mContentGravity | Gravity.CENTER_VERTICAL);
    
            mFlContent.removeAllViews();
            mFlContent.addView(tvContent);
    
            AutoUtils.autoTextSize(tvContent);
        }
    
        //是否有二级页面
        if (mIsHasNextPage) {
            mIvNext.setVisibility(VISIBLE);
            this.setOnClickListener(v -> {
                mLisenter.onClickItem(mContentTxt);
            });
        } else {
            mIvNext.setVisibility(INVISIBLE);
        }
    
        AutoUtils.autoSize(this);
    }
    
    @Override
    public EditLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new EditLayout.LayoutParams(getContext(), attrs);
    }
    
    public static class LayoutParams extends RelativeLayout.LayoutParams implements AutoLayoutHelper.AutoLayoutParams {
        private AutoLayoutInfo mAutoLayoutInfo;
    
        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
            mAutoLayoutInfo = AutoLayoutHelper.getAutoLayoutInfo(c, attrs);
        }
    
        @Override
        public AutoLayoutInfo getAutoLayoutInfo() {
            return mAutoLayoutInfo;
        }
    }
    
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (!isInEditMode()) {
            mHelper.adjustChildren();
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
    
    //整个Item的点击事件
    public interface onEditLayoutEventLisenter {
        void onClickItem(String content);
    }
    
    public void setOnEditLayoutEventLisenter(onEditLayoutEventLisenter onClickItemLisenter) {
        mLisenter = onClickItemLisenter;
    }
    

    }

    lay_edit_layout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout 
                    xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:background="@color/white"
                    android:layout_height="150px"
                    android:paddingLeft="36px"
                    android:paddingRight="36px">
    
        <TextView
            android:id="@+id/tv_txt_tag"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:ems="4"
            android:textColor="#333333"
            android:textSize="48px"/>
    
        <FrameLayout
            android:id="@+id/fl_content"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_centerVertical="true"
            android:layout_marginRight="36px"
            android:layout_toLeftOf="@+id/iv_next"
            android:layout_toRightOf="@+id/tv_txt_tag"
            android:background="@color/white"/>
    
        <ImageView
            android:id="@+id/iv_next"
            android:layout_width="26px"
            android:layout_height="47px"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:background="@drawable/ic_arrow"/>
    
    </RelativeLayout>
    

    test_editlayout.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"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:background="@color/default_bg"
                  android:orientation="vertical">
    
        <com.example.myapplication2.EditLayout
               android:id="@+id/et_layout1"
        android:layout_width="match_parent"
        android:layout_height="@dimen/px150"
        app:content_txt="我是标题"
        app:content_widget="textview"
        app:has_next_page="true"
        app:hint_txt="请填写标题"
        app:tag_txt="标题"/>
    
        <View style="@style/view_title"/>
    
        <com.example.myapplication2.EditLayout
            android:id="@+id/et_layout2"
        android:layout_width="match_parent"
        android:layout_height="@dimen/px150"
        app:content_txt="我是内容"
        app:content_widget="edittext"
        app:hint_txt="请填写内容"
        app:tag_txt="内容"/>
    
        <View style="@style/view_title"/>
    
        <com.example.myapplication2.EditLayout
           android:id="@+id/et_layout3"
        android:layout_width="800px"
        android:layout_height="@dimen/px150"
        app:content_widget="textview"
        app:hint_txt="请填写公司地址"
        app:tag_txt="公司地址"/>
    
        <Button
            android:id="@+id/btn_click"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="设置我啊"/>
    
    </LinearLayout>
    

    attrs.xml

    <!--EditLayout-->
        <declare-styleable name="EditLayout">
              <attr name="tag_color" format="color|reference"/>
        <attr name="hint_color" format="color|reference"/>
        <attr name="content_color" format="color|reference"/>
        <attr name="tag_size" format="dimension"/>
        <attr name="content_size" format="dimension"/>
        <attr name="has_next_page" format="boolean"/>
        <attr name="tag_txt" format="string|reference"/>
        <attr name="hint_txt" format="string|reference"/>
        <attr name="content_txt" format="string|reference"/>
        <attr name="lines" format="integer"/>
        <attr name="max_line" format="integer"/>
        <attr name="ellipsize">
            <enum name="start" value="0"/>
            <enum name="middle" value="1"/>
            <enum name="end" value="2"/>
            <enum name="marquee" value="3"/>
        </attr>
        <attr name="content_widget">
            <enum name="edittext" value="0"/>
            <enum name="textview" value="1"/>
        </attr>
        <attr name="content_gravity">
            <enum name="left" value="-1"/>
            <enum name="center" value="0"/>
            <enum name="right" value="1"/>
        </attr>
        <attr name="input_type">
            <enum name="number" value="0"/>
            <enum name="text" value="1"/>
            <enum name="date" value="2"/>
            <enum name="datetime" value="3"/>
            <enum name="numberDecimal" value="4"/>
            <enum name="numberPassword" value="5"/>
            <enum name="numberSigned" value="6"/>
            <enum name="phone" value="7"/>
            <enum name="textAutoComplete" value="8"/>
            <enum name="textAutoCorrect" value="9"/>
            <enum name="textEmailAddress" value="10"/>
            <enum name="textFilter" value="11"/>
            <enum name="textPassword" value="12"/>
            <enum name="textPersonName" value="13"/>
            <enum name="textUri" value="14"/>
            <enum name="textVisiblePassword" value="15"/>
        </attr>
        </declare-styleable>
    

    colors.xml

        <color name="default_gray_light">#999999</color>
        <color name="default_black">#333333</color>
        <color name="white">#ffffff</color>
        <color name="default_bg">#f2f2f2</color>
        <color name="default_line">#dddddd</color>
    

    styles.xml

       <!-- 分割线 -->
        <style name="view_title">
            <item name="android:layout_width">match_parent</item>
            <item name="android:layout_height">1px</item>
            <item name="android:background">@color/default_line
          </item>
        </style>
    

    另外我在app的build.gradle里引入了

    java8

    compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
    }
    

    和张鸿洋的AutoLayout
    https://github.com/hongyangAndroid/AndroidAutoLayout

    compile 'com.zhy:autolayout:1.4.5'
    

    相关文章

      网友评论

          本文标题:Android 自定义编辑控件

          本文链接:https://www.haomeiwen.com/subject/pcipmxtx.html