Android EditText 文本内容超过文本框失去焦点后,超出文本框内容显示...

产品OR测试提出优化需求,输入的文字长度超过输入框,则超出的文本用…显示,当获取焦点的时候,显示全部内容,光标又要移动到最后。

思路:
    1、第一想到的肯定是“ellipsize”属性设置为“end”,android:ellipsize=“end”。这个在文本框TextView有效,EditText未起作用,亲测。
    2、设置固定宽度,或者看下固定文字,比如你设定的文本框只能显示十个中文字符就占满了,但如果输入了英文或者数字则长度又不好计算了,并且测试那还有N种手机屏幕在那等着来轮奸你呢,早点放弃为好!

    3、得到输入文本框EditText的宽度,得到字符串的宽度,然后对比,字符串宽度>文本框宽度,就substring掉。这目前应该是最好的了方案了,并且Android提供了计算文本宽度的方法。

第一次尝试着写文章,排版逻辑什么的不怎么规范,还请多包涵!

开干:
    建项目就略了。

1、布局文件: activity_main.xml
           
Code Text:
<? xml version= "1.0" encoding= "utf-8" ?>
<LinearLayout xmlns: android = " http://schemas.android.com/apk/res/android "
    xmlns: tools = " http://schemas.android.com/tools "
    android :layout_width= "match_parent"
    android :layout_height= "match_parent"
    android :background= "#f2f2f2
     android :focusable= "true"
     android :focusableInTouchMode= "true"
    tools :context= "com.threefei.rou.MainActivity" >
    <ScrollView
        android :layout_width= "match_parent"
        android :layout_height= "match_parent"
        android :fillViewport= "true"
        android :scrollbarSize= "0dp"
        android :scrollbars= "none" >
        <LinearLayout
            android :layout_width= "match_parent"
            android :layout_height= "wrap_content"
            android :orientation= "vertical" >

            <LinearLayout
                android :layout_width= "match_parent"
                android :layout_height= "50dp"
                android :background= "@android:color/white"
                android :orientation= "horizontal"
                android :paddingLeft= "15dp"
                android :paddingRight= "15dp" >

                <TextView
                    android :layout_width= "100dp"
                    android :layout_height= "match_parent"
                    android :gravity= "center_vertical"
                    android :text= "收件人地址:" />

                <EditText
                    android :id= "@+id/et_address_1"
                    android :layout_width= "match_parent"
                    android :layout_height= "match_parent"
                    android :background= "@null"
                    android :gravity= "center_vertical"
                    android :maxLength= "30"
                    android :maxLines= "1"
                    android :singleLine= "true"
                    android :textSize= "12sp" />

            </LinearLayout>

            <View
                android :layout_width= "match_parent"
                android :layout_height= "0.5dp"
                android :background= "@android:color/darker_gray" />

            <LinearLayout
                android :layout_width= "match_parent"
                android :layout_height= "50dp"
                android :background= "@android:color/white"
                android :orientation= "horizontal"
                android :paddingLeft= "15dp"
                android :paddingRight= "15dp" >

                <TextView
                    android :layout_width= "100dp"
                    android :layout_height= "match_parent"
                    android :gravity= "center_vertical"
                    android :text= "发件人地址:" />

                <EditText
                    android :id= "@+id/et_address_2"
                    android :layout_width= "match_parent"
                    android :layout_height= "match_parent"
                    android :background= "@null"
                    android :gravity= "center_vertical"
                    android :maxLength= "30"
                    android :maxLines= "1"
                    android :singleLine= "true"
                    android :text= ""
                    android :textSize= "12sp" />

            </LinearLayout>

            <View
                android :layout_width= "match_parent"
                android :layout_height= "0.5dp"
                android :background= "@android:color/darker_gray" />

            <TextView
                android :id= "@+id/tv_result"
                android :layout_width= "match_parent"
                android :layout_height= "wrap_content"
                android :layout_margin= "20dp"
                android :background= "@android:color/white"
                android :hint= "提交结果值"
                android :padding= "10dp"
                android :minHeight= "150dp" />

            <Button
                android :id= "@+id/btn_click"
                android :layout_width= "match_parent"
                android :layout_height= "48dp"
                android :layout_margin= "25dp"
                android :gravity= "center"
                android :text= "提交" />

        </LinearLayout>
    </ScrollView>
</LinearLayout>

Code Design:

2、Activity: MainActivity.java
    1)按产品的要求,那肯定得设置EditText的 setOnFocusChangeListener。
    2)获得焦点的时候,得把原来超过长度范围值(原始值)设置到setText(String val),这个原始值,可以放到外面的成员变量里,也可以放到 EditText的tag里,这里的tag还没有其他用途,所以我把值放到tag里。
    3)失去焦点的时候,得判断输入框的字符串是否大于控件的宽度,大于则截掉超出范围的字符串。
         a. EditText.setSelection(int index) 可以把光标定位到某个文字后面
         b.  TextView.getPaint().measureText(String text) 可以得到字符串的宽度
         c. 循环计算追加每个字符串的长度 > 文本框的长度
         d. 最后substring


public class MainActivity extends Activity implements View.OnClickListener , View.OnFocusChangeListener {

    private static final int CODE_MSG_ADDRESS_1 = 1 ;
    private static final int CODE_MSG_ADDRESS_2 = 2 ;

    private EditText mEtAddress1 , mEtAddress2 ;
    private TextView mTvResult ;

    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super .onCreate(savedInstanceState) ;
        setContentView(R.layout. activity_main ) ;

        mEtAddress1 = (EditText) findViewById(R.id. et_address_1 ) ;
        mEtAddress2 = (EditText) findViewById(R.id. et_address_2 ) ;

        //提前先设置tag,避免在onFocuse里出现对象转换异常
        mEtAddress1 .setTag( "" ) ;
        mEtAddress2 .setTag( "" ) ;

        mEtAddress1 .setOnFocusChangeListener( this ) ;
        mEtAddress2 .setOnFocusChangeListener( this ) ;

        mTvResult = (TextView) findViewById(R.id. tv_result ) ;

        findViewById(R.id. btn_click ).setOnClickListener( this ) ;
    }

    @Override
    public void onWindowFocusChanged ( boolean hasFocus) {
        super .onWindowFocusChanged(hasFocus) ;
        if (hasFocus) {
            //Activity的话,初始化赋值,可以在onWindowFocusChanged里设置,执行到这,控件的宽高可以得到了
            //这个val可以从其他地方传过来
            String val = "幸福省幸福市幸福区幸福路幸福小区x栋xx号" ;
            formartEditTextViewVal( mEtAddress2 , val) ;
        }
    }


    @Override
    public void onClick (View v) {
        mEtAddress1 .clearFocus() ;
        mEtAddress2 .clearFocus() ;

        //真实的值放到了tag里了
        String address1 = mEtAddress1 .getTag().toString() ;
        String address2 = mEtAddress2 .getTag().toString() ;

        StringBuilder sb = new StringBuilder( "收件人地址:" ).append(address1) ;
        sb.append( " \n 发件人地址:" ).append(address2) ;

        mTvResult .setText(sb.toString()) ;
    }

    @Override
    public void onFocusChange (View v , boolean hasFocus) {
        switch (v.getId()) {
            case R.id . et_address_1 :
                if (hasFocus) {
                    String text = mEtAddress1 .getTag().toString().trim() ;
                    mEtAddress1 .setText(text) ;
                    mHandler .sendEmptyMessage( CODE_MSG_ADDRESS_1 ) ;

                    //直接在这里设置光标移动到最后,这句代码无效,所以用到Handler跳出该方法,再设置光标
//                    UITools.setEditTextCursorEnd(mEtAddress1);

                } else {
                    String text = mEtAddress1 .getText().toString().trim() ;
                    formartEditTextViewVal( mEtAddress1 , text) ;
                }
                break;

            case R.id . et_address_2 :
                if (hasFocus) {
                    String text = mEtAddress2 .getTag().toString().trim() ;
                    mEtAddress2 .setText(text) ;
                    mHandler .sendEmptyMessage( CODE_MSG_ADDRESS_2 ) ;

                } else {
                    String text = mEtAddress2 .getText().toString().trim() ;
                    formartEditTextViewVal( mEtAddress2 , text) ;
                }
                break;
        }
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage (Message msg) {
            super .handleMessage(msg) ;
            if (msg. what == CODE_MSG_ADDRESS_1 ) {
                UITools. setEditTextCursorEnd ( mEtAddress1 ) ;

            } else if (msg. what == CODE_MSG_ADDRESS_2 ) {
                UITools. setEditTextCursorEnd ( mEtAddress2 ) ;
            }
        }
    } ;

    /**
     * 格式化值
     *
     * @param editText
     * @param text
     */
    private void formartEditTextViewVal (EditText editText , String text) {
        editText.setTag(text) ;
        String str = UITools. getEllipsisValue (text , editText) ;
        editText.setText(str) ;
    }
}



补充下:使用Fragment初始化View获取控件宽高

/**
  *  getViewTreeObserver的 vto.addOnGlobalLayoutListener<br/>
  * 可以得到控件的宽高
   */
void onGlobalLayout () {
    //向ViewTreeObserver 注册方法,以获取控件尺寸
    ViewTreeObserver vto = mEtAddress1 .getViewTreeObserver() ;
    vto.addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() {
        public void onGlobalLayout () {
            formartEditTextViewVal ( mEtAddress1 , "传递的值" ) ;
            mEtAddress1 .getViewTreeObserver().removeGlobalOnLayoutListener( this ) ;
        }
    }) ;
}




3、工具类: UITools.java

public class UITools {
    /**
     * 将EditTextView的光标移动到最后
     *
     * @param editText
     */
    public static void setEditTextCursorEnd (EditText editText) {
        editText.setSelection(editText.getText().toString().length()) ;
    }

    /**
     * 获取字符串所占屏幕长度
     *
     * @param text
     * @param textView
     * @return
     */
    public static float getTextValueWidth (String text , TextView textView) {
        if ( null == text || "" .equals(text)) {
            return 0 ;
        }
        TextPaint textPaint = textView.getPaint() ;
        return textPaint.measureText(text) ;
    }

    /**
     * 计算字符串宽度超过文本框宽度的时候,显示带...的字符串
     *
     * @param text
     * @param textView
     * @return
     */
    public static String getEllipsisValue (String text , TextView textView) {
        String total = "" ;
        float textViewWdith = textView.getWidth() ;
//        Log.e("xb", "-->文本框宽度:" + textViewWdith);
        boolean isCut = false;

          //循环计算追加后的字符串长度是否大于文本框长度
        for ( int i = 1 ; i <= text.length() ; i++) {
            total = text.substring( 0 , i) ;
            float totalWdith = getTextValueWidth (total , textView) ;
//            Log.e("xb", "-->当前字符长度:" + totalWdith + ",字符串:" + total);
            if (totalWdith > textViewWdith) {
                isCut = true;
                break;
            }
        }

        //这里判断文本框长度是为了,有时候粗心,在view没有绘制好的时候,得到的宽度为0,不然substring就蹦了
        if (isCut && textViewWdith > 0 ) {
            //可以截取3,但"..."占大概2个中文字符宽度左右
            return total.substring( 0 , total.length() - 2 ) + "..." ;
        }
        return text ;
    }

    /**
     * Toast提示
     *
     * @param context
     * @param msg
     */
    public static void showToast (Context context , String msg) {
        Toast. makeText (context , msg , Toast. LENGTH_SHORT ).show() ;
    }

}


4、运行效果图


这里可以重写EditText,把逻辑放到重写类里去,使用就方便多了。
其实在项目中,文本框输入还有N种需求,
1、屏蔽特殊字符,或者屏蔽表情符号
2、只能输入中文或者英文
3、带一键删除按钮的EditTextView等
4、银行卡类型的格式化输入等要求

小bug提示:有的手机,貌似是moto手机,你设置了maxLength = 10,但测试在输入法中一次性敲打超过十个字的文本,可以跳过maxLength的设置,所以又得监听addTextChangedListener了。

案例下载地址: http://download.csdn.net/download/liang_fei_xp/9968644
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值