Android tip 2

Posted by valoukh on Mon, 03 Jan 2022 19:43:32 +0100

[27.EditText soft keyboard]

EditText does not pop up the soft keyboard initially, only the cursor is displayed, click and then pop up
Solution 1:
Set in the activity property of the manifest

android:windowSoftInputMode="stateHidden"

Solution 2:

InputMethodManager inputMethodManager = (InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(et.getWindowToken(), 0);

Solution 3:
By default, the first EditText gets the focus. The solution is to add a view that is not displayed to force the focus, such as

<View 
android:layout_width="0dip"
android:layout_height="0dip"
android:focusableInTouchMode="true" />

[hide soft keyboard - not verified]

// *Hide software disk
public void hideSoftInput() {
    InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
    if (getCurrentFocus() != null) {
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
    }
}
 
// *Click the blank space outside the soft keyboard to hide the software disk
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        View v = getCurrentFocus();
        if (ToolUtil.isShouldHideInput(v, ev)) {
 
            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            if (imm != null) {
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
        return super.dispatchTouchEvent(ev);
    }
    // Essential, otherwise all components will not have TouchEvent
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    return onTouchEvent(ev);
}
 
// *Display soft keyboard
public void showInputMethod(){
    if (getCurrentFocus() != null){
        InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
        imm.showSoftInputFromInputMethod(getCurrentFocus().getWindowToken(),0);
    }
}

[soft keyboard does not block the input box]
https://blog.csdn.net/u012523122/article/details/52101303/

Method 1: in your activity Medium oncreate in setContentView Write this code before
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

Method 2: at the beginning of the project AndroidManifest.xml Add in the corresponding interface in the file
android:windowSoftInputMode="stateVisible|adjustResize"
This will move the screen up as a whole.
If you add android:windowSoftInputMode="adjustPan"The keyboard will cover the screen.

Meaning of each value:
stateUnspecified: The state of the soft keyboard is not specified. The system will select an appropriate state or theme dependent settings
stateUnchanged: When this activity When it appears, the soft keyboard will remain in the previous position activity The state in the, whether hidden or displayed
stateHidden: User selection activity When, the soft keyboard is always hidden
stateAlwaysHidden: When Activity When the main window gets the focus, the soft keyboard is always hidden
stateVisible: Soft keyboards are usually visible
stateAlwaysVisible: User selection activity When, the soft keyboard always displays the status
adjustUnspecified: The default setting, which is usually hidden or displayed at the discretion of the system
adjustResize: Should Activity Always resize the screen to make room for the soft keyboard
adjustPan: The content of the current window will automatically move so that the current focus is never covered by the keyboard and the user can always see the part of the input content

Method 3:(Use here)
Put the top layout replace with ScrollView,Or at the top Layout Add another layer on top ScrollView. 
This will scroll the soft keyboard with the input box, and the soft keyboard will always be at the bottom.
General top View Need to add android: fitsSystemWindows="true"

[28. Timer] (note that it is not a delayer)

1. postDelayed method of handler class:

Handler mHandler = new Handler();
Runnable r = new Runnable() {
    @Override
    public void run() {
        //do something
        //Execute the run method every 1s
        mHandler.postDelayed(this, 1000);
    }
};
Call in main thread:  mHandler.postDelayed(r, 100);//100 ms delay

2. Use the handler+timer+timeTask method:

Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1){
                //do something
            }
            super.handleMessage(msg);
        }
};

Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            Message message = new Message();
            message.what = 1;
            handler.sendMessage(message);
        }
};
Call in main thread: timer.schedule(timerTask,1000,500);//The run method is executed every 500 milliseconds with a delay of 1 s

3.Thread+handler method:

Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1){
                //do something
            }
            super.handleMessage(msg);
        }
};

class MyThread extends Thread {//The Runnable interface can also be used here
        @Override
        public void run() {
            while (true){
                try {
                    Thread.sleep(1000);//Every 1s
                    Message msg = new Message();
                    msg.what = 1;
                    handler.sendMessage(msg);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
}
Call in main thread: new Thread(new MyThread()).start();

[29. Delay device]

1.Handler's postDelayed method:

new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
              //do something
          }
}, 1000);    //Delay 1s for execution

2.timer + TimerTask method:

Timer timer = new Timer();
timer.schedule(new TimerTask() {                   
      @Override
      public void run() {
              //do something
      }
},1000);//Delay 1s for execution

3.Thread method:

new Thread(new MyThread()).start();
//or
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);//Delay 1s
            //do something
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}).start();

[30.TextView sliding up and down, left and right sliding settings]

1. Vertical sliding

  android:scrollbars = "vertical"

2. Horizontal sliding

  android:scrollbars = "horizontal"
  android:scrollbars="none" //Do not display scroll bar

Must be added in Java (otherwise cannot slide)

  ArrowKeyMovementMethod.getInstance()  //level
  tx.setMovementMethod(ScrollingMovementMethod.getInstance());  /vertical

To add: android:ellipsize = "none"
android:singleLine="true"
3. Set the scroll bar to always exist

  android:fadeScrollbars="false"

4. Customize scroll bar properties

  android:scrollbarThumbVertical="@drawable/bar"

5. Running lamp:

android:singleLine="true"
android:ellipsize="marquee"

https://blog.csdn.net/beiminglei/article/details/9317997

//Set the character width (in fact, em is a unit of printing layout, indicating the unit of word width) to 10,
//Generally, one Chinese character is one width,
android:maxEms="10"  
//When the value is 1-5, m = n
6-11 When, m = n+1. 
12-18 When, m = n+2. 

[31. Prevent quick click]

private static long lastClick = 0;
private boolean fastClick() {
    if (System.currentTimeMillis() - lastClick <= 1000) {
        return false;
    }
    lastClick = System.currentTimeMillis();
    return true;
}

[32.EditText input content]

In code
//InputType. TYPE_ NUMBER_ FLAG_ The code of decimal is 8192, and what we need is 8194, which is android:inputType="numberDecimal",
 //But there is no constant, so we need to enter the number manually
editText.setInputType(8194);

android:digits="1234567890."   ====  editText.setInputType(EditorInfo.TYPE_CLASS_PHONE); 

InputType.TYPE_CLASS_NUMBER    Number type 1234567890
InputType.TYPE_CLASS_DATETIME  Date type 1234567890/-
//Custom digits( https://www.jianshu.com/p/691b00e750c7 )
editText.setKeyListener(DigitsKeyListener.getInstance("0123456789-"));
android:inputType="none"--Enter normal characters
android:inputType="text"--Enter normal characters
android:inputType="textCapCharacters"--Enter normal characters
android:inputType="textCapWords"--Word initial size
android:inputType="textCapSentences"--First letter size only
android:inputType="textAutoCorrect"--The first two are automatically completed
android:inputType="textAutoComplete"--The first two are automatically completed
android:inputType="textMultiLine"--Multiline input
android:inputType="textImeMultiLine"--Input method multiple lines (not necessarily supported)
android:inputType="textNoSuggestions"--No hint
android:inputType="textUri"--URI format
android:inputType="textEmailAddress"--Email address format
android:inputType="textEmailSubject"--Message subject format
android:inputType="textShortMessage"--Short message format
android:inputType="textLongMessage"--Long message format
android:inputType="textPersonName"--Person name format
android:inputType="textPostalAddress"--Postal format
android:inputType="textPassword"--Password format
android:inputType="textVisiblePassword"--Password visible format
android:inputType="textWebEditText"--Text format as a web form
android:inputType="textFilter"--Text filter format
android:inputType="textPhonetic"--Pinyin input format
android:inputType="number"--Digital format
android:inputType="numberSigned"--Signed number format
android:inputType="numberDecimal"--Floating point format with decimal point
android:inputType="phone"--Dialing keyboard
android:inputType="datetime"
android:inputType="date"--Date keyboard
android:inputType="time"--Time keyboard

EditText has a default height, and setHeight does not work.

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
        DensityUtil.dip2px(context, 25));
layoutParams.setMargins(0, 0, 0, 0);
editText.setIncludeFontPadding(false);//Remove inner margin
//Maximum input length
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(10)}); //Maximum input length
[kotlin Version: editText.filters = arrayOf(InputFilter.LengthFilter(24))]
editText.setInputType(InputType.TYPE_CLASS_NUMBER); //Digital input type
editText.setTextColor(context.getResources().getColor(R.color.color_888888));
editText.setPadding(10, 0, 0, 1);//Otherwise, the text display is incomplete
editText.setLayoutParams(layoutParams);//This is so that the width and height can be set. Otherwise, the default height is 80 (with inner margin) / 75
editText.setBackground(null); //Remove underline and all formatting

Style:

android:background="@null"//The style of the cursor has not changed, the underline has disappeared, and the margin has disappeared

Cursor style

<EditText
    android:text=" "//The initial cursor moves back one unit
	android:textCursorDrawable="@drawable/color_cursor"//Set cursor width and color

take textCursorDrawable Set to@null,Indicates that the system default style is removed
 The properties of the hidden cursor are android:cursorVisible,The color of the cursor is the same as the text android:textColor bring into correspondence with

sendText.setSelection(sendText.getText().length()); //Cursor last
sendText.setSelection(0, sendText.getText().length()); //Check all

Underline change style: https://www.jb51.net/article/121010.htm

//Use this
<style name="MyEditText" parent="Theme.AppCompat.Light"> 
 <item name="colorControlNormal">@color/indigo</item> //The default color of the control
 <item name="colorControlActivated">@color/pink</item>//The color when the control is activated
</style>

<EditText 
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:hint="Hint text"
android:theme="@style/MyEditText"/>

//other
et_underline_unselected.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
     <item
          android:bottom="0dp"
          android:left="-2dp"
          android:right="-2dp"
          android:top="-2dp">
              <shape>
                   <solid android:color="@android:color/transparent" />
                   <stroke
                        android:width="1dp"
                        android:color="@android:color/darker_gray" />
                   <padding android:bottom="4dp" />
              </shape>
     </item>
</layer-list>

et_underline_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
     <item
          android:bottom="0dp"
          android:left="-2dp"
          android:right="-2dp"
          android:top="-2dp">
              <shape>
                   <solid android:color="@android:color/transparent" />
                   <stroke
                        android:color="@android:color/holo_green_light"
                        android:width="2dp" />
                   <padding android:bottom="4dp" />
              </shape>
     </item>
</layer-list>

//First:
<EditText
      android:id="@+id/editText1"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_margin="3dp"
      android:background="@null"
      android:hint="custom EditText Underline 1"
      android:textCursorDrawable="@drawable/cursor_color" />
      
/**Initialize EditText, which is unchecked by default**/
editText1.setBackgroundResource(R.drawable.et_underline_unselected);

/**The focus listening event of the first EditText**/
editText1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
     @Override
     public void onFocusChange(View v, boolean hasFocus) {
          if (hasFocus) {
           Log.e(TAG, "EditText1 Get focus");
           editText1.setBackgroundResource(R.drawable.et_underline_selected);
          } else {
           Log.e(TAG, "EditText1 Lose focus");
           editText1.setBackgroundResource(R.drawable.et_underline_unselected);
          }
     }
});

//Second
et_underline_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_focused="false" android:drawable="@drawable/et_underline_unselected"/>
     <item android:state_focused="true" android:drawable="@drawable/et_underline_selected"/>
</selector>

<EditText
      android:id="@+id/editText1"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_margin="3dp"
      android:background="@drawable/et_underline_selector"
      android:hint="custom EditText Underline 1"
      android:textCursorDrawable="@drawable/cursor_color" />
      
cursor_color.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
     <size android:width="2dp" />
     <solid android:color="@android:color/holo_blue_light" />
</shape>

[33. Android base64 encryption and decryption]

The Android project cannot reference the following two java classes

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

Android has its own base64 class

import android.util.Base64

String str = "Hello!";  
//base64 encoding  
//String strBase64 = new String(Base64.encode(str.getBytes(), Base64.DEFAULT));  
String strBase64 = Base64.encodeToString(str.getBytes(), Base64.DEFAULT);  
//base64 decoding  
String str2 = new String(Base64.decode(strBase64.getBytes(), Base64.DEFAULT));

[34. String splicing in Java - delete the last character]

str.split("\|"); // Escape character

StringBuilder builder = new StringBuilder();
for (int i = 0; i < 5; i++) {
    builder.append("aaa").append(",");
}
System.out.println(builder.toString());

if (builder.length() <= 0) {
    return;
}
//Or String with equals = = = is the same as the length segment above
if ("".contentEquals(time)) {
    return;
}

String aaa = builder.substring(0, builder.length() - 1);
System.out.println(aaa);

//1.deleteCharAt
builder = builder.deleteCharAt(builder.length() - 1);
System.out.println(builder.toString());

//2. [used] if not, return - 1
builder = builder.deleteCharAt(builder.lastIndexOf(","));
System.out.println(builder);

//3.setLength
builder.setLength(builder.length() - 1);
System.out.println(builder);

//Java 8 has a new StringJoiner built in
StringJoiner joiner = new StringJoiner(",");
for (int i = 0; i < 5; i++) {
    joiner.add("bbb");
}
System.out.println(joiner);

//Other - add a delimiter before it, and then delete it
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5; i++) {
    sb.append(",").append(i);
}
sb = sb.deleteCharAt(0);
System.out.println(sb);

//output
 original: aaa,aaa,aaa,aaa,aaa,
substring: aaa,aaa,aaa,aaa,aaa
deleteCharAt + length: aaa,aaa,aaa,aaa,aaa  //be careful
deleteCharAt + lastIndexOf: aaa,aaa,aaa,aaaaaa //Note that I assign this value to the original builder
setLength: aaa,aaa,aaa,aaaaa //Note that I assign this value to the original builder
Joiner: bbb,bbb,bbb,bbb,bbb
 Prefix: 0,1,2,3,4

[string interception in JS]

var str = 'Hello World!';
str=str.slice(0,str.length-1)  //Method 1 (can be negative): Hello World
str=str.substr(0,str.length-1) //Mode 2 (can be negative): Hello World
str=str.substring(0,str.length-1)//Mode 3 (cannot be negative): Hello World
str=str.substring(0, str.lastIndexOf('!'));  

str = str.substr(1); //Delete the first character ello World!

[35. Date string comparison size]

//The first method directly uses the compareTo method of string class:
public static boolean compareNowDate1(String t1, String t2) {
    int result = t1.compareTo(t2);
    //If result > 0, T1 > T2;
    //Result < = 0, T1 < = T2
    return result > 0;
}

//The second method is to convert the date string to long:
public static boolean compareNowDate1(String t1, String t2) {
    SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
    try {
        Date d1 = format.parse(t1);
        Date d2 = format.parse(t2);
        long result = d1.getTime() - d2.getTime();
        //Result > = 0, then value is greater than or equal to now
        //If result < 0, then value is less than now
        return result > 0;
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return false;
}

//The third is to convert the date string into an integer int:
public static boolean compareNowDate1(String t1, String t2) {
    //You can try catch
    int int1 = Integer.parseInt(t1);
    int int2 = Integer.parseInt(t2);
    int result = int1 - int2;
    //Result > = 0, then value is greater than or equal to now
    //If result < 0, then value is less than now
    return result > 0;
}

[Fan Wai: delete git account]

[generate public key: SSH keygen - t RSA - C“ xxxx@xxx.com ”]Third carriage return
git extracts the Authentication failed and incorrect username or password (access token) of the project
Then how to extract it is the same, and you will not be prompted to enter your account and password again;
terms of settlement:
1. The control panel enters the user account
2. Click Manage windows credentials

[36. Hide App interface and icon]

<application
    ...
    android:theme="@android:style/Theme.NoDisplay">
    
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
    
            <category android:name="android.intent.category.LAUNCHER" />
            <!--No startup page-->
            <data
                android:host=".app"
                android:pathPrefix="/openwith"
                android:scheme="myapp" />
        </intent-filter>
    </activity>
</application>    
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:theme="@android:style/Theme.NoDisplay">

</LinearLayout>

//No startup page
//setContentView(R.layout.activity_main)

[39. Draw width and height]

https://blog.csdn.net/chenbaige/article/details/77991594
Get the size (width and height) of the View in the activity. If you only write getWidth() and getHeight(), you can't get the width and height of the View
Question answer: in fact, the measure process of View and the life cycle method of Activity are not executed synchronously. Therefore, it is impossible to ensure that the View has been measured when the Activity completes executing a life cycle method. In this case, the obtained size is 0.

//1. Get the following from the onWindowFocusChanged method of the activity: 
//When the onWindowFocusChanged method is executed, it means that the View has been initialized, the width and height have been measured and finally confirmed,
//onWindowFocusChanged will be executed multiple times and will be called once when the Activity gets focus and loses focus.
// That is, the onPause and onResume methods are called repeatedly when they are executed.
@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        int width = bbb.getMeasuredWidth();
        int height = bbb.getMeasuredHeight();
        ZLog.e("1.view Width:" + width + "  view Height:" + height);
    }
}

//2.View.post method
//When the runable method is executed, all initialization measurement method descriptions of View have been executed.
view.post(new Runnable() {
    @Override
    public void run() {
        int width = bbb.getMeasuredWidth();
        int height = bbb.getMeasuredHeight();
        ZLog.e("2.view Width:" + width + "  view Height:" + height);
    }
});

//3.ViewTreeObserver
//When the state of the View tree changes or the visibility of the View inside the View tree changes, onGlobalLayout will be called back.
//Note: onGlobalLayout will be called multiple times as the state of the View tree changes.
ViewTreeObserver observer = view.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        int width = view.getMeasuredWidth();
        int height = view.getMeasuredHeight();
        ZLog.e("3.view Width:" + width + "  view Height:" + height);
        aaa.setMaxWidth(widthP - width - 10);//I'm late. aaa has exceeded this time. width=0
    }
});

//4.measure
//After manually calling measure, the View will call the onMeasure method to initiate measurement on the View. After measurement, you can obtain the measured width and height.
//However, specific parameter values can only be obtained by processing the LayoutParams parameters according to different situations:
//4.1) the LayoutParams parameter of view is match_parent:
    //In this case, the specific width and height value cannot be obtained, because when the measurement mode of View is match_ When parent, the width and height value takes the remaining space of the parent container as its own width and height.
    //At this time, the size of the parent container cannot be obtained, so the acquisition will fail.
//4.2) the LayoutParams parameter of view is the specific value: (0?)
int widthV = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.EXACTLY);
int heigtV = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.EXACTLY);
bbb.measure(widthV, heigtV);
int width1 = bbb.getMeasuredWidth();
int height1 = bbb.getMeasuredHeight();
ZLog.e("4.view Width:" + width1 + "  view Height:" + height1);

//4.3) wrap_content: Yes
int width22 = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
int height22 = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
bbb.measure(width22, height22);
int height222 = bbb.getMeasuredHeight();
int width222 = bbb.getMeasuredWidth();
ZLog.e("5.view Width:" + width222 + "  view Height:" + height222);
//aaa.setMaxWidth(widthP - width222 - 10);

[I use this]
//(can be used) Note: View.MeasureSpec.UNSPECIFIED
//4.1 when the TextView attribute is wrap_ How to obtain the width of content, especially when the interface is not displayed, such as in RecycleView
int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
bbb.measure(spec, spec);
int width11 = bbb.getMeasuredWidth();
int height11 = bbb.getMeasuredHeight();
ZLog.e("4.1 view Width:" + width11 + "  view Height:" + height11);

[40. Basic type to string]

float + "" has a + sign. It operates in the constant pool and generates two. therefore
String.valueOf (float) is relatively good.
In addition: + comparison with StringBuider https://mp.weixin.qq.com/s/dc7HW0SqEcJknMIqoQZnlg

[41.TextView discoloration]

https://weilu.blog.csdn.net/article/details/52863741

text.setText(Html.fromHtml("Commodity code<font color=red>*</font>:"));
text.setText(Html.fromHtml(String.format("Commodity code<font color=red>*</font>:%s","22")));
//Note: html returns Spanned, not a string. It inherits CharSequence
//Some other of HTML: https://blog.csdn.net/baidu_34012226/article/details/53301047

//2 types: https://www.jianshu.com/p/f004300c6920 Include setting size
SpannableStringBuilder builder = new SpannableStringBuilder(bar_code);
int index = bar_code.indexOf(etScan);
builder.setSpan(new ForegroundColorSpan(Color.RED), index,
        index + etScan.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(builder);

//Link form
android:autoLink Set whether the text is URL link/email/number/map When, the text is displayed as a clickable link.
Optional values: none/web/Email/phone/map/all

android:lineSpacingExtra="8dp"  //Is the row spacing. It defaults to 0, which is an absolute height value.
lineSpacingMultiplier Property, which represents the multiple of row spacing. The default is 1.0f,Is a relative height value.
android:text="Method of picking up parts: pick up parts from door to door\n Express company: SF Express"

[42. Limit the number of decimal places entered in EditText]

① Restricted input types in xml:

android:inputType="numberDecimal"

② Override InputFilter

public class DecimalDigitsInputFilter implements InputFilter {

    private final int decimalDigits;

    public DecimalDigitsInputFilter(int digits) {
        this.decimalDigits = digits;
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        // source: the character currently entered
        // Start: enter the start position of the character
        // End: enter the end position of the character
        // dest: currently displayed content
        // dstart: current cursor start position
        // dent: current cursor end position
        //Log.e("", "source=" + source + ",start=" + start + ",end=" + end + ",dest=" + dest.toString() + ",dstart=" + dstart + ",dend=" + dend);
        if (dest.length() == 0 && source.equals(".")) {
            return "0.";
        }
        String dValue = dest.toString();
        String[] splitArray = dValue.split("\\.");
        if (splitArray.length > 1) {
            String dotValue = splitArray[1];
            //When the decimal digits of the input box are decimalDigits, the decimal digits cannot be input, and the integer digits can be input normally
            if (dotValue.length() == decimalDigits && dest.length() - dstart <= decimalDigits) {
                return "";
            }
        }
        return null;
    }
}

③ Set the number of decimal places. 2 digits are passed in here

edit.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(2)});

[TextView code setting expansion and omission]

//TextView code setting expansion and omission
textView.setOnClickListener(v -> {
    if (isShowDes) {
        textView.setEllipsize(TextUtils.TruncateAt.END);
        textView.setSingleLine();
    } else {
        textView.setEllipsize(null);
        textView.setSingleLine(false);
    }
    isShowDes = !isShowDes;
});

Topics: Android