From 5f89160ee19d1d8dd8e8a43bf471fab130fd9e3b Mon Sep 17 00:00:00 2001 From: CatherineFXX <648129313@qq.com> Date: Fri, 20 Oct 2017 14:44:13 +0800 Subject: [PATCH] =?UTF-8?q?(#2)=20code=20=E6=B7=BB=E5=8A=A0TSUserIntroduce?= =?UTF-8?q?InputView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zhiyicx/tsui/utils/TSConvertUtils.java | 49 +++++ .../widget/edittext/TSInputLimitView.java | 10 +- .../edittext/TSUserIntroduceInputView.java | 201 ++++++++++++++++++ .../layout/ts_view_input_limit_viewgroup.xml | 21 +- .../ts_view_userinfo_introduce_inputview.xml | 35 +++ tsui/src/main/res/values/tsui_colors.xml | 2 + tsui/src/main/res/values/tsui_dimens.xml | 1 + tsui/src/main/res/values/tsui_strings.xml | 1 + tsuidemo/src/main/AndroidManifest.xml | 3 +- .../main/res/layout/activity_ts_edittext.xml | 15 +- tsuidemo/src/main/res/values/strings.xml | 3 +- 11 files changed, 321 insertions(+), 20 deletions(-) create mode 100644 tsui/src/main/java/com/zhiyicx/tsui/widget/edittext/TSUserIntroduceInputView.java create mode 100644 tsui/src/main/res/layout/ts_view_userinfo_introduce_inputview.xml diff --git a/tsui/src/main/java/com/zhiyicx/tsui/utils/TSConvertUtils.java b/tsui/src/main/java/com/zhiyicx/tsui/utils/TSConvertUtils.java index dc349a4..18a02c6 100644 --- a/tsui/src/main/java/com/zhiyicx/tsui/utils/TSConvertUtils.java +++ b/tsui/src/main/java/com/zhiyicx/tsui/utils/TSConvertUtils.java @@ -59,4 +59,53 @@ public static int px2sp(Context context, float pxValue) { return (int) (pxValue / fontScale + 0.5f); } + /** + * 替换 emoji 长度 =1 + * + * @param str + * @return + */ + public static int stringLengthDealForEmoji(CharSequence str) { + int emojiLength = emojiStrLength(str); + return (str.length() - emojiLength) + stringEmojiCount(str); + } + + /** + * @param str + * @return 一个 emoji 占两个字,通过长度返回个数 + */ + public static int stringEmojiCount(CharSequence str) { + int emojiLenght = emojiStrLength(str); + return emojiLenght / 2; + } + + /** + * @param str + * @return 字符串中 emoji 字符长度 + */ + public static int emojiStrLength(CharSequence str) { + int emojiLenght = 0; + int len = str.length(); + for (int i = 0; i < len; i++) { + if (isEmojiCharacter(str.charAt(i))) { + emojiLenght++; + } + } + return emojiLenght; + } + + /** + * emoji 所占的长度 + * @param emojiNUm emoji 个数 + * @return + */ + public static int emojiStrLength(int emojiNUm) { + return 2*emojiNUm; + } + + private static boolean isEmojiCharacter(char codePoint) { + return !(codePoint == 0x0 || codePoint == 0x9 || codePoint == 0xA || codePoint == 0xD || codePoint >= 0x20 && codePoint <= 0xD7FF || + codePoint >= 0xE000 && codePoint <= 0xFFFD); + } + } diff --git a/tsui/src/main/java/com/zhiyicx/tsui/widget/edittext/TSInputLimitView.java b/tsui/src/main/java/com/zhiyicx/tsui/widget/edittext/TSInputLimitView.java index 9a47927..84e14fe 100644 --- a/tsui/src/main/java/com/zhiyicx/tsui/widget/edittext/TSInputLimitView.java +++ b/tsui/src/main/java/com/zhiyicx/tsui/widget/edittext/TSInputLimitView.java @@ -22,7 +22,7 @@ /** * @Describe 限制输入控件 view - * @Author Jungle68 + * @author Jungle68 * @Date 2017/1/12 * @Contact master.jungle68@gmail.com */ @@ -134,7 +134,7 @@ public void afterTextChanged(Editable s) { if (s.length() >= mShowLimitSize) { mLimitTipStr = "<" + s.length() + ">" + "/" + mLimitMaxSize; CharSequence chars = TSColorPhrase.from(mLimitTipStr).withSeparator("<>") - .innerColor(ContextCompat.getColor(context, R.color.tsui_config_color_red)) + .innerColor(ContextCompat.getColor(context, R.color.tsui_config_color_red_note)) .outerColor(ContextCompat.getColor(context, R.color.tsui_general_for_hint)) .format(); mTvLimitTip.setText(chars); @@ -171,10 +171,10 @@ public void setOnSendClickListener(OnSendClickListener onSendClickListener) { /** * 设置发送按钮是否显示 * - * @param isVisiable true 显示 + * @param isVisible true 显示 */ - public void setSendButtonVisiable(boolean isVisiable) { - if (isVisiable) { + public void setSendButtonVisible(boolean isVisible) { + if (isVisible) { mBtSend.setVisibility(VISIBLE); } else { mBtSend.setVisibility(GONE); diff --git a/tsui/src/main/java/com/zhiyicx/tsui/widget/edittext/TSUserIntroduceInputView.java b/tsui/src/main/java/com/zhiyicx/tsui/widget/edittext/TSUserIntroduceInputView.java new file mode 100644 index 0000000..ae3fd64 --- /dev/null +++ b/tsui/src/main/java/com/zhiyicx/tsui/widget/edittext/TSUserIntroduceInputView.java @@ -0,0 +1,201 @@ +package com.zhiyicx.tsui.widget.edittext; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.v4.content.ContextCompat; +import android.text.Editable; +import android.text.InputFilter; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.zhiyicx.tsui.R; +import com.zhiyicx.tsui.utils.TSColorPhrase; +import com.zhiyicx.tsui.utils.TSConvertUtils; + +import static android.support.annotation.Dimension.SP; + +/** + * @author LiuChao + * @describe 用户个人资料,简介编辑框 + * @date 2017/1/17 + * @contact email:450127106@qq.com + */ + +public class TSUserIntroduceInputView extends FrameLayout { + /** + * 提示 格式xx/xx + */ + protected TextView mTvLimitTip; + /** + * 输入EditText + */ + protected EditText mEtContent; + /** + * 最大输入值 + */ + private int mLimitMaxSize; + /** + * 当输入值达到 mShowLimitSize 时,显示提示 + */ + private int mShowLimitSize; + /** + * 编辑框的hint提示文字 + */ + private String mHintContent; + /** + * 编辑框显示最大行数,超过改行数就滚动 + */ + private int mShowLines; + /** + * 输入文字的内容 + */ + private int mContentGravity; + /** + * 监听输入框输入内容变化 + */ + private ContentChangedListener mContentChangedListener; + + /** + * 添加格式符号,用户TSColorPhrase + */ + private String mLimitTipStr = "{}/"; + + /** + * 对外提供 获取输入EditText + * + * @return EditText + */ + public EditText getEtContent() { + return mEtContent; + } + + public TSUserIntroduceInputView(Context context) { + super(context); + init(context, null); + } + + public TSUserIntroduceInputView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public TSUserIntroduceInputView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(final Context context, AttributeSet attrs) { + LayoutInflater.from(context).inflate(R.layout.ts_view_userinfo_introduce_inputview, this); + mTvLimitTip = findViewById(R.id.tv_limit_tip); + mEtContent = findViewById(R.id.et_content); + if (attrs != null) { + TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TSInputLimitView); + mLimitMaxSize = array.getInteger(R.styleable.TSInputLimitView_tsLimitSize, context.getResources().getInteger(R.integer.comment_input_max_size)); + mShowLimitSize = array.getInteger(R.styleable.TSInputLimitView_tsShowLimitSize, context.getResources().getInteger + (R.integer.show_comment_input_size)); + mHintContent = array.getString(R.styleable.TSInputLimitView_tsHintContent); + // 如果为0就不要设置maxLine了 + mShowLines = array.getInteger(R.styleable.TSInputLimitView_tsShowLines, 0); + // 如果为0就不要设置maxLine了 + mContentGravity = array.getInteger(R.styleable.TSInputLimitView_tsContent_gravity, Gravity.START); + mEtContent.setGravity(mContentGravity); + if (array.getDimensionPixelSize(R.styleable.TSInputLimitView_tsContent_size, 0) != 0) { + mEtContent.setTextSize(SP, TSConvertUtils.px2dp(getContext(), array.getDimension(R.styleable.TSInputLimitView_tsContent_size, 0))); + } + array.recycle(); + } else { + mLimitMaxSize = context.getResources().getInteger(R.integer.comment_input_max_size); + mShowLimitSize = context.getResources().getInteger(R.integer.show_comment_input_size); + mHintContent = context.getResources().getString(R.string.tsui_edit_introduce); + mShowLines = 0; + } + + // 初始化控件属性 2*mLimitMaxSize 用于兼容 emoji + mEtContent.setFilters(new InputFilter[]{new InputFilter.LengthFilter(2 * mLimitMaxSize)}); + mEtContent.setHint(mHintContent); + if (mShowLines > 0) { + mEtContent.setLines(mShowLines); + } + mTvLimitTip.setVisibility(GONE); + mEtContent.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) { + if (mContentChangedListener != null) { + mContentChangedListener.contentChanged(s); + } + } + + @Override + public void afterTextChanged(Editable s) { + // 一下是处理适配 emoji, 让emoji 算成一个长度 + int parseContentLength = TSConvertUtils.stringLengthDealForEmoji(s); + mLimitTipStr = "<" + parseContentLength + ">" + "/" + mLimitMaxSize; + int emojiNum = TSConvertUtils.stringEmojiCount(s); + mEtContent.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mLimitMaxSize + emojiNum + 1)}); + if (parseContentLength > mLimitMaxSize) { + String shouldShowContent = s.toString().substring(0, s.toString().length() - (parseContentLength - mLimitMaxSize)); + int shouldShowEmojiNum = TSConvertUtils.stringEmojiCount(shouldShowContent); + int offset = emojiNum - shouldShowEmojiNum; + if (offset > 0) { + TSConvertUtils.emojiStrLength(offset); + shouldShowContent = shouldShowContent.substring(0, shouldShowContent.length() - offset); + } + mEtContent.setText(shouldShowContent); + mEtContent.setSelection(shouldShowContent.length()); + } + if (parseContentLength >= mShowLimitSize) { + CharSequence chars = TSColorPhrase.from(mLimitTipStr).withSeparator("<>") + .innerColor(ContextCompat.getColor(context, R.color.tsui_config_color_red_note)) + .outerColor(ContextCompat.getColor(context, R.color.tsui_general_for_hint)) + .format(); + mTvLimitTip.setText(chars); + mTvLimitTip.setVisibility(VISIBLE); + mEtContent.setPadding(0, 0, 0, context.getResources().getDimensionPixelSize(R.dimen.tsui_default_30)); + } else { + mTvLimitTip.setVisibility(GONE); + mEtContent.setPadding(0, 0, 0, 0); + } + } + }); + } + + /** + * 获取输入内容 + * + * @return 当前输入内容,去掉前后空格 + */ + public String getInputContent() { + return mEtContent.getText().toString().trim(); + } + + public void setText(String content) { + mEtContent.setText(content); + } + + /** + * 因为控件使用了TextChangedListener,无法在外面再次创建一个监听 + * 获取控件,在某些时候需要用到 + */ + public void setContentChangedListener(ContentChangedListener contentChangedListener) { + mContentChangedListener = contentChangedListener; + } + + public interface ContentChangedListener { + /** + * 内容改变 + * + * @param s 内容 + */ + void contentChanged(CharSequence s); + } +} diff --git a/tsui/src/main/res/layout/ts_view_input_limit_viewgroup.xml b/tsui/src/main/res/layout/ts_view_input_limit_viewgroup.xml index a0e0216..31966f5 100644 --- a/tsui/src/main/res/layout/ts_view_input_limit_viewgroup.xml +++ b/tsui/src/main/res/layout/ts_view_input_limit_viewgroup.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@color/tsui_config_color_white"> + android:background="@color/input_view_bg_color"> @@ -24,8 +24,7 @@ @@ -42,22 +41,20 @@ android:gravity="center" android:textColor="@color/tsui_config_color_white" android:textSize="@dimen/tsui_text_size_14" - android:visibility="gone"/> + android:visibility="gone" + /> \ No newline at end of file diff --git a/tsui/src/main/res/layout/ts_view_userinfo_introduce_inputview.xml b/tsui/src/main/res/layout/ts_view_userinfo_introduce_inputview.xml new file mode 100644 index 0000000..00c6af4 --- /dev/null +++ b/tsui/src/main/res/layout/ts_view_userinfo_introduce_inputview.xml @@ -0,0 +1,35 @@ + + + + + + + + \ No newline at end of file diff --git a/tsui/src/main/res/values/tsui_colors.xml b/tsui/src/main/res/values/tsui_colors.xml index 1d87618..7a8085f 100644 --- a/tsui/src/main/res/values/tsui_colors.xml +++ b/tsui/src/main/res/values/tsui_colors.xml @@ -25,6 +25,7 @@ #1B88EE #801B88EE #FA3A3A + #f4504d #DEE0E2 #D4D6D8 #F4F5F7 @@ -88,6 +89,7 @@ + #333333 #cccccc #80cccccc #fafafa diff --git a/tsui/src/main/res/values/tsui_dimens.xml b/tsui/src/main/res/values/tsui_dimens.xml index 976a87e..ea2e363 100644 --- a/tsui/src/main/res/values/tsui_dimens.xml +++ b/tsui/src/main/res/values/tsui_dimens.xml @@ -43,6 +43,7 @@ + 10sp 11sp 13sp 14sp diff --git a/tsui/src/main/res/values/tsui_strings.xml b/tsui/src/main/res/values/tsui_strings.xml index ada4df5..d8d89d7 100644 --- a/tsui/src/main/res/values/tsui_strings.xml +++ b/tsui/src/main/res/values/tsui_strings.xml @@ -13,4 +13,5 @@ 没有任何内容 网络不可用,请检查! 加载中 + 编辑简介 diff --git a/tsuidemo/src/main/AndroidManifest.xml b/tsuidemo/src/main/AndroidManifest.xml index 5ee2456..47ffb22 100644 --- a/tsuidemo/src/main/AndroidManifest.xml +++ b/tsuidemo/src/main/AndroidManifest.xml @@ -21,7 +21,8 @@ android:screenOrientation="portrait"/> + android:screenOrientation="portrait" + android:windowSoftInputMode="adjustPan"/> diff --git a/tsuidemo/src/main/res/layout/activity_ts_edittext.xml b/tsuidemo/src/main/res/layout/activity_ts_edittext.xml index a625143..9c8da8b 100644 --- a/tsuidemo/src/main/res/layout/activity_ts_edittext.xml +++ b/tsuidemo/src/main/res/layout/activity_ts_edittext.xml @@ -72,7 +72,20 @@ edit:tsLimitSize="20" edit:tsShowLimitSize="15" edit:tsShowLines="5" - edit:tsContent_gravity="right" + edit:tsContent_gravity="left" edit:tsContent_size="17sp"/> + + + + \ No newline at end of file diff --git a/tsuidemo/src/main/res/values/strings.xml b/tsuidemo/src/main/res/values/strings.xml index ff1e027..e159ea0 100644 --- a/tsuidemo/src/main/res/values/strings.xml +++ b/tsuidemo/src/main/res/values/strings.xml @@ -6,7 +6,8 @@ 密码输入框 信息输入输入框,可以设置是否必填等等 带有前缀的输入框 - 带有限制长度的输入框 + 带有限制长度和按钮的输入框 + 带有限制长度的用户信息输入框 可以设置 drawable 大小的 TextView 可以展开与收起的TextView,可以设置1、最高展示行数 2、展开与收起的文字内容颜色等等啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦绿啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦绿啦啦啦啦啦啦啦