Apakah ada cara untuk menentukan nilai min dan maks untuk EditText di Android?

133

Saya ingin mendefinisikan nilai min dan maks untuk EditText.

Misalnya: jika ada orang yang mencoba memasukkan nilai bulan di dalamnya, nilainya harus antara 1-12.

Saya dapat melakukannya dengan menggunakan TextWatchertetapi saya ingin tahu apakah ada cara lain untuk melakukannya di file layout atau di tempat lain.

Sunting: Saya tidak ingin membatasi jumlah karakter. Saya ingin membatasi nilainya. Misalnya, jika saya membatasi bulan dengan EditTextkarakter ketika saya memasukkan 12 itu akan menerimanya tetapi jika saya memasukkan 22 itu tidak boleh menerimanya saat saya memasukkan.

mertaydin
sumber
Seseorang harus membuat perpustakaan / koleksi semua jenis filter input ini. Lalu semua orang bisa bekerja dan mengujinya bersama. Daripada setiap orang melakukan hal mereka sendiri.
Zapnologica
Gunakan filter teks edit ini untuk menyelesaikan masalah Anda. filter
Taras Smakula

Jawaban:

286

Pertama buat kelas ini:

package com.test;

import android.text.InputFilter;
import android.text.Spanned;

public class InputFilterMinMax implements InputFilter {

    private int min, max;

    public InputFilterMinMax(int min, int max) {
        this.min = min;
        this.max = max;
    }

    public InputFilterMinMax(String min, String max) {
        this.min = Integer.parseInt(min);
        this.max = Integer.parseInt(max);
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {   
        try {
            int input = Integer.parseInt(dest.toString() + source.toString());
            if (isInRange(min, max, input))
                return null;
        } catch (NumberFormatException nfe) { }     
        return "";
    }

    private boolean isInRange(int a, int b, int c) {
        return b > a ? c >= a && c <= b : c >= b && c <= a;
    }
}

Kemudian gunakan ini dari Aktivitas Anda:

EditText et = (EditText) findViewById(R.id.myEditText);
et.setFilters(new InputFilter[]{ new InputFilterMinMax("1", "12")});

Ini akan memungkinkan pengguna untuk memasukkan nilai dari 1 hingga 12 saja .

EDIT:

Atur edittext Anda dengan android:inputType="number".

Anda dapat menemukan detail lebih lanjut di https://www.techcompose.com/how-to-set-minimum-and-maximum-value-in-edittext-in-android-app-development/ .

Terima kasih.

Pratik Sharma
sumber
1
@mertaydin yakin. Cobalah, beri tahu saya jika Anda membutuhkan bantuan saya. Terima kasih.
Pratik Sharma
12
Aah, aku butuh bantuan. Saya memiliki masalah saat nilai writig antara 1930 dan 1999. Ketika saya menulis 1 itu mengendalikan nilai dan 1 tidak antara 1930 dan 1999 sehingga tidak menerimanya.
mertaydin
1
@mertaydin Hei maaf tapi saya sedikit sibuk dengan pekerjaan saya. Saya baru saja melihat beberapa hal, saya pikir saya perlu melakukan modifikasi pada algoritma yang diterapkan di kelas filter. Saya akan memperbarui Anda setelah saya selesai dengan itu.
Pratik Sharma
1
Beberapa karakter dari sourceakan menggantikan beberapa karakter dalam dest. Saya pikir Anda harus mensimulasikan penggantian, dan mendapatkan hasil akhir, lalu, validasi.
SD
3
@Pratik Sharma, Ini tidak berfungsi ketika saya memasuki rentang 1900 hingga 2000, Bisakah Anda menyarankan sesuatu
EminenT
89

Ada kesalahan kecil dalam kode Pratik. Misalnya, jika nilai 10 dan Anda menambahkan 1 di awal untuk membuat 110, fungsi filter akan memperlakukan nilai baru sebagai 101.

Lihat di bawah untuk perbaikannya:

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        // Remove the string out of destination that is to be replaced
        String newVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend, dest.toString().length());
        // Add the new string in
        newVal = newVal.substring(0, dstart) + source.toString() + newVal.substring(dstart, newVal.length());
        int input = Integer.parseInt(newVal);
        if (isInRange(min, max, input))
            return null;
    } catch (NumberFormatException nfe) { }
    return "";
}
Zac
sumber
Terima kasih, ini banyak membantu saya!
joschplusa
4
Saya pikir ini lebih jelas imho :String replacement = source.subSequence(start, end).toString(); String newVal = dest.subSequence(0, dstart).toString() + replacement + dest.subSequence(dend, dest.length()).toString();
Sven Jacobs
1
+1. solusi ini lebih benar daripada yang diterima. Untuk memeriksanya misalnya coba gunakan InputFilterMinMax dengan opsi selectAllOnFocus diaktifkan dan bandingkan hasilnya.
Sash0k
1
Kenapa tidak String newVal= dest.toString().substring(0, dstart) + source.toString().substring(start, end) + dest.toString().substring(dend, dest.toString().length());, terlihat lebih bersih dan jernih.
Shishir Gupta
5
Seperti yang disebutkan oleh OP @mertaydin dalam komentar pada jawaban @ Patrick, solusi ini masih memiliki kelemahan besar, saya bertanya-tanya mengapa hal itu tidak dilaporkan: Jika min==3kemudian tidak mungkin untuk mengetikkan angka apa pun yang dimulai dengan 1 atau 2 (mis: 15, 23)
Guerneen4
10

Dari apa yang saya lihat tentang solusi @ Patrik dan penambahan @ Zac, kode yang diberikan masih memiliki masalah besar:

Jika min==3kemudian tidak mungkin untuk mengetik angka apa pun yang dimulai dengan 1 atau 2 (mis: 15, 23)
Jika min>=10kemudian tidak mungkin untuk mengetik apa pun karena setiap angka harus dimulai dengan 1,2,3 ...

Dalam pemahaman saya, kami tidak dapat mencapai batasan min-max dari EditTextnilai suatu dengan penggunaan kelas yang sederhana InputFilterMinMax, setidaknya tidak untuk nilai min, karena ketika pengguna mengetikkan angka positif, nilainya bertambah dan kami dapat dengan mudah melakukan on-the-fly test untuk memeriksa apakah sudah mencapai batas atau keluar dari jangkauan dan memblokir entri yang tidak sesuai. Menguji nilai min adalah cerita yang berbeda karena kami tidak dapat memastikan apakah pengguna telah selesai mengetik atau tidak dan karena itu tidak dapat memutuskan apakah kami harus memblokir atau tidak.

Ini bukan apa yang diminta OP tetapi untuk tujuan validasi saya telah dikombinasikan dalam solusi saya InputFilteruntuk menguji nilai-nilai maks, dengan OnFocusChangeListeneruntuk menguji ulang nilai min ketika EditTextkehilangan fokus dengan asumsi pengguna selesai mengetik dan itu seperti ini:

package test;


import android.text.InputFilter;

import android.text.Spanned;

public class InputFilterMax implements InputFilter {

private int max;

public InputFilterMax(int max) {
    this.max = max;
}

public InputFilterMax(String max) {
    this.max = Integer.parseInt(max);
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {   
    try {
        String replacement = source.subSequence(start, end).toString(); 

        String newVal = dest.toString().substring(0, dstart) + replacement +dest.toString().substring(dend, dest.toString().length());

        int input = Integer.parseInt(newVal);

        if (input<=max)
            return null;
    } catch (NumberFormatException nfe) { }   
//Maybe notify user that the value is not good      
return "";
}
}

Dan OnFocusChangeListenerMin

package test;

import android.text.TextUtils;
import android.view.View;
import android.view.View.OnFocusChangeListener;

public class OnFocusChangeListenerMin implements OnFocusChangeListener {

private int min;

public OnFocusChangeListenerMin(int min) {
    this.min = min;
}

public OnFocusChangeListenerMin(String min) {
    this.min = Integer.parseInt(min);
}


@Override
public void onFocusChange(View v, boolean hasFocus) {
    if(!hasFocus) {
        String val = ((EditText)v).getText().toString();
        if(!TextUtils.isEmpty(val)){
            if(Integer.valueOf(val)<min){
                //Notify user that the value is not good
            }

        }
    }
}
}

Kemudian di Activity atur InputFilterMaxdan OnFocusChangeListenerMinuntuk EditText diperhatikan: Anda dapat 2 menit minimum dan maksimum onFocusChangeListener.

mQteEditText.setOnFocusChangeListener( new OnFocusChangeListenerMin('20');
mQteEditText.setFilters(new InputFilter[]{new InputFilterMax(getActivity(),'50')});
Guerneen4
sumber
OnFocusChangeListenerMin tidak berfungsi, ia meletakkan semua nilai dari nol
EminenT
1
Apakah Anda keberatan merinci lebih banyak? apa maksudmu meletakkan semua nilai dari nol ?
Guerneen4
dari kode OnFocusChangeListenerMin harus bekerja di atas 20 seperti yang dibahas dalam masalah tetapi ia menerima semua nilai kurang dari 20 seperti 0, 1, 2, ------ 19 dll
EminenT
apakah Anda menemukan solusi?
EminenT
Saya telah menggunakan OnFoncusChangeListener untuk tujuan validasi, dalam kasus saya saya menampilkan kesalahan pada EditText memberi tahu pengguna dengan Toast bahwa nilainya tidak baik dan mengundangnya untuk memasukkan nilai baru. if(Integer.valueOf(val)<min){ //Notify user that the value is not good } Anda dapat melakukan apa yang Anda inginkan di sana, beri tahu pengguna dan set EditText menjadi kosong, saya tidak tahu apakah ini menjawab pertanyaan Anda
Guerneen4
9

Perpanjangan jawaban Pratik dan Zac. Zac memperbaiki bug kecil milik Pratik dalam jawabannya. Tapi saya mencatat bahwa kode tidak mendukung nilai negatif, itu akan melempar NumberFormatException. Untuk memperbaikinya, dan biarkan MIN negatif, gunakan kode berikut.

Tambahkan baris ini (Tebal) di antara dua baris lainnya:

newVal = newVal.substring (0, dstart) + source.toString () + newVal.substring (dstart, newVal.length ());

jika (newVal.equalsIgnoreCase ("-") && min <0) mengembalikan nol;

input int = Integer.parseInt (newVal);

public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        // Remove the string out of destination that is to be replaced
        String newVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend, dest.toString().length());
        // Add the new string in
        newVal = newVal.substring(0, dstart) + source.toString() + newVal.substring(dstart, newVal.length());
        //****Add this line (below) to allow Negative values***// 
        if(newVal.equalsIgnoreCase("-") && min < 0)return null;
        int input = Integer.parseInt(newVal);
        if (isInRange(min, max, input))
            return null;
    } catch (NumberFormatException nfe) {
        nfe.printStackTrace();
    }
    return "";
}
Anthony B
sumber
5

Jika Anda membutuhkan rentang dengan angka negatif seperti -90: 90, Anda dapat menggunakan solusi ini.

public class InputFilterMinMax implements InputFilter {

private int min, max;

public InputFilterMinMax(int min, int max) {
    this.min = min;
    this.max = max;
}

public InputFilterMinMax(String min, String max) {
    this.min = Integer.parseInt(min);
    this.max = Integer.parseInt(max);
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        String stringInput = dest.toString() + source.toString();
        int value;
        if (stringInput.length() == 1 && stringInput.charAt(0) == '-') {
            value = -1;
        } else {
            value = Integer.parseInt(stringInput);
        }
        if (isInRange(min, max, value))
            return null;
    } catch (NumberFormatException nfe) {
    }
    return "";
}

private boolean isInRange(int min, int max, int value) {
    return max > min ? value >= min && value <= max : value >= max && value <= min;
}
}
Denys Vasylenko
sumber
5

Saya memperluas kode @Pratik Sharmas untuk menggunakan objek BigDecimal alih-alih int sehingga dapat menerima angka yang lebih besar, dan memperhitungkan setiap pemformatan di EditText yang bukan angka (seperti pemformatan mata uang, misalnya spasi, koma, dan titik)

EDIT: perhatikan bahwa implementasi ini memiliki 2 sebagai angka signifikan minimum yang ditetapkan pada BigDecimal (lihat konstanta MIN_SIG_FIG) seperti yang saya gunakan untuk mata uang, jadi selalu ada 2 angka utama sebelum titik desimal. Ubah konstanta MIN_SIG_FIG seperlunya untuk implementasi Anda sendiri.

public class InputFilterMinMax implements InputFilter {
private static final int MIN_SIG_FIG = 2;
private BigDecimal min, max;

public InputFilterMinMax(BigDecimal min, BigDecimal max) {
    this.min = min;
    this.max = max;
}

public InputFilterMinMax(String min, String max) {
    this.min = new BigDecimal(min);
    this.max = new BigDecimal(max);
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
        int dend) {
    try {
        BigDecimal input = formatStringToBigDecimal(dest.toString()
                + source.toString());

        if (isInRange(min, max, input)) {

            return null;
        }
    } catch (NumberFormatException nfe) {

    }
    return "";
}

private boolean isInRange(BigDecimal a, BigDecimal b, BigDecimal c) {
    return b.compareTo(a) > 0 ? c.compareTo(a) >= 0 && c.compareTo(b) <= 0
            : c.compareTo(b) >= 0 && c.compareTo(a) <= 0;
}

public static BigDecimal formatStringToBigDecimal(String n) {

    Number number = null;
    try {
        number = getDefaultNumberFormat().parse(n.replaceAll("[^\\d]", ""));

        BigDecimal parsed = new BigDecimal(number.doubleValue()).divide(new BigDecimal(100), 2,
                BigDecimal.ROUND_UNNECESSARY);
        return parsed;
    } catch (ParseException e) {
        return new BigDecimal(0);
    }
}

private static NumberFormat getDefaultNumberFormat() {
    NumberFormat nf = NumberFormat.getInstance(Locale.getDefault());
    nf.setMinimumFractionDigits(MIN_SIG_FIG);
    return nf;
}
AndroidNoob
sumber
4

Saya menemukan jawaban saya sendiri. Sekarang sudah sangat terlambat, tetapi saya ingin membaginya dengan Anda. Saya mengimplementasikan antarmuka ini:

import android.text.TextWatcher;


public abstract class MinMaxTextWatcher implements TextWatcher {
    int min, max;
    public MinMaxTextWatcher(int min, int max) {
        super();
        this.min = min;
        this.max = max;
    }

}

Dan kemudian implementasikan dengan cara ini di dalam aktivitas Anda:

private void limitEditText(final EditText ed, int min, int max) {
    ed.addTextChangedListener(new MinMaxTextWatcher(min, max) {
        @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) {
            String str = s.toString();
            int n = 0;
            try {
                n = Integer.parseInt(str);
                if(n < min) {
                    ed.setText(min);
                    Toast.makeText(getApplicationContext(), "Minimum allowed is " + min, Toast.LENGTH_SHORT).show();
                }
                else if(n > max) {
                    ed.setText("" + max);
                    Toast.makeText(getApplicationContext(), "Maximum allowed is " + max, Toast.LENGTH_SHORT).show();
                }
            }
            catch(NumberFormatException nfe) {
                ed.setText("" + min);
                Toast.makeText(getApplicationContext(), "Bad format for number!" + max, Toast.LENGTH_SHORT).show();
            }
        }
    });
}

Ini adalah jawaban yang sangat sederhana, jika ada yang lebih baik tolong beri tahu saya.

Nash Makineta
sumber
int n = 0; berlebihan. Karena nilai default n adalah 0.
Kenny Dabiri
1
Mengapa int n = 0 berlebihan di sini? ini merupakan variabel lokal dan bukan variabel instan di sini.
User12111111
4

Ada yang salah dalam jawaban yang diterima.

int input = Integer.parseInt(dest.toString() + source.toString());

Jika saya memindahkan kursor ke tengah teks, lalu mengetik sesuatu, maka pernyataan di atas akan menghasilkan hasil yang salah. Misalnya, ketik "12" pertama, lalu ketik "0" antara 1 dan 2, maka pernyataan yang disebutkan di atas akan menghasilkan "120", bukan 102. Saya mengubah pernyataan ini menjadi pernyataan di bawah ini:

String destString = dest.toString();
  String inputString = destString.substring(0, dstart) + source.toString() + destString.substring(dstart);
  int input = Integer.parseInt(inputString);
谭春茂
sumber
4

Kotlin jika ada yang membutuhkannya (Gunakan Utilitas)

class InputFilterMinMax: InputFilter {
    private var min:Int = 0
    private var max:Int = 0
    constructor(min:Int, max:Int) {
        this.min = min
        this.max = max
    }
    constructor(min:String, max:String) {
        this.min = Integer.parseInt(min)
        this.max = Integer.parseInt(max)
    }
    override fun filter(source:CharSequence, start:Int, end:Int, dest: Spanned, dstart:Int, dend:Int): CharSequence? {
        try
        {
            val input = Integer.parseInt(dest.toString() + source.toString())
            if (isInRange(min, max, input))
                return null
        }
        catch (nfe:NumberFormatException) {}
        return ""
    }
    private fun isInRange(a:Int, b:Int, c:Int):Boolean {
        return if (b > a) c in a..b else c in b..a
    }
}

Kemudian gunakan ini dari kelas Kotlin Anda

percentage_edit_text.filters = arrayOf(Utilities.InputFilterMinMax(1, 100))

EditText ini memungkinkan dari 1 hingga 100.

Kemudian gunakan ini dari XML Anda

android:inputType="number"
Alish
sumber
Saya menggunakan sumber kembali dan bekerja untuk saya ==> if (isInRange (min, max, input)) sumber kembali
Muzafferus
3

Saya membuat cara yang lebih sederhana untuk mengatur min / max ke Edittext. Saya menggunakan keypad aritmatika dan saya bekerja dengan metode ini:

 private int limit(EditText x,int z,int limin,int limax){

    if( x.getText().toString()==null || x.getText().toString().length()==0){
        x.setText(Integer.toString(limin));
        return z=0;
    }
    else{
        z = Integer.parseInt(x.getText().toString());
         if(z <limin || z>limax){
             if(z<10){
                 x.setText(Integer.toString(limin));
                return  z=0;
             }
            else{
                x.setText(Integer.toString(limax));
                return z=limax;
            }

         }
         else
            return z = Integer.parseInt(x.getText().toString());
    }
 }

Metode ini menerima semua nilai Anda tetapi jika nilai pengguna tidak mematuhi batas Anda, maka akan ditetapkan secara otomatis ke batas min / maks. Misalnya batas limin = 10, limax = 80 jika pengguna menetapkan 8, secara otomatis 10 disimpan ke variabel dan EditTeks diatur ke 10.

Argyris
sumber
3

Saya tahu sudah ada jutaan jawaban untuk ini, dengan satu jawaban diterima. Namun, ada banyak bug dalam jawaban yang diterima dan sebagian besar sisanya hanya memperbaiki satu (atau mungkin dua), tanpa memperluas ke semua kasus penggunaan yang mungkin.

Jadi pada dasarnya saya mengkompilasi sebagian besar perbaikan bug yang disarankan dalam jawaban dukungan serta menambahkan metode untuk memungkinkan input nomor yang terus menerus di luar rentang ke arah 0 (jika rentang tidak mulai dari 0), setidaknya sampai yakin bahwa itu tidak lagi berada dalam jangkauan. Karena harus jelas, ini adalah satu-satunya waktu yang benar-benar menyebabkan masalah dengan banyak solusi lain.

Inilah solusinya:

public class InputFilterIntRange implements InputFilter, View.OnFocusChangeListener {

    private final int min, max;

    public InputFilterIntRange(int min, int max) {
        if (min > max) {
            // Input sanitation for the filter itself
            int mid = max;
            max = min;
            min = mid;
        }
        this.min = min;
        this.max = max;
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

        // Determine the final string that will result from the attempted input
        String destString = dest.toString();
        String inputString = destString.substring(0, dstart) + source.toString() + destString.substring(dstart);

        // Don't prevent - sign from being entered first if min is negative
        if (inputString.equalsIgnoreCase("-") && min < 0) return null;

        try {
            int input = Integer.parseInt(inputString);
            if (mightBeInRange(input))
                return null;
        } catch (NumberFormatException nfe) {}

        return "";
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {

        // Since we can't actively filter all values
        // (ex: range 25 -> 350, input "15" - could be working on typing "150"),
        // lock values to range after text loses focus
        if (!hasFocus) {
            if (v instanceof EditText) sanitizeValues((EditText) v);
        }
    }

    private boolean mightBeInRange(int value) {
        // Quick "fail"
        if (value >= 0 && value > max) return false;
        if (value >= 0 && value >= min) return true;
        if (value < 0 && value < min) return false;
        if (value < 0 && value <= max) return true;

        boolean negativeInput = value < 0;

        // If min and max have the same number of digits, we can actively filter
        if (numberOfDigits(min) == numberOfDigits(max)) {
            if (!negativeInput) {
                if (numberOfDigits(value) >= numberOfDigits(min) && value < min) return false;
            } else {
                if (numberOfDigits(value) >= numberOfDigits(max) && value > max) return false;
            }
        }

        return true;
    }

    private int numberOfDigits(int n) {
        return String.valueOf(n).replace("-", "").length();
    }

    private void sanitizeValues(EditText valueText) {
        try {
            int value = Integer.parseInt(valueText.getText().toString());
            // If value is outside the range, bring it up/down to the endpoint
            if (value < min) {
                value = min;
                valueText.setText(String.valueOf(value));
            } else if (value > max) {
                value = max;
                valueText.setText(String.valueOf(value));
            }
        } catch (NumberFormatException nfe) {
            valueText.setText("");
        }
    }

}

Perhatikan bahwa beberapa kasus input tidak mungkin untuk menangani "secara aktif" (yaitu, karena pengguna memasukkannya), jadi kita harus mengabaikannya dan menanganinya setelah pengguna selesai mengedit teks.

Begini cara Anda menggunakannya:

EditText myEditText = findViewById(R.id.my_edit_text);
InputFilterIntRange rangeFilter = new InputFilterIntRange(25, 350);
myEditText.setFilters(new InputFilter[]{rangeFilter});

// Following line is only necessary if your range is like [25, 350] or [-350, -25].
// If your range has 0 as an endpoint or allows some negative AND positive numbers, 
// all cases will be handled pre-emptively.
myEditText.setOnFocusChangeListener(rangeFilter);

Sekarang, ketika pengguna mencoba mengetikkan angka lebih dekat ke 0 daripada rentang yang diizinkan, salah satu dari dua hal akan terjadi:

  1. Jika mindan maxmemiliki jumlah digit yang sama, mereka tidak akan diizinkan untuk memasukkannya sama sekali begitu mereka mencapai digit terakhir.

  2. Jika angka di luar rentang dibiarkan di bidang ketika teks kehilangan fokus, maka secara otomatis akan disesuaikan dengan batas terdekat.

Dan tentu saja, pengguna tidak akan pernah diizinkan untuk memasukkan nilai lebih jauh dari 0 daripada rentang memungkinkan, juga tidak mungkin untuk nomor seperti itu untuk "tidak sengaja" berada di bidang teks karena alasan ini.

Masalah Dikenal?)

  1. Ini hanya berfungsi jika EditTextkehilangan fokus ketika pengguna selesai dengan itu.

Pilihan lain adalah membersihkan ketika pengguna menekan tombol "selesai" / kembali, tetapi dalam banyak atau bahkan kebanyakan kasus, ini menyebabkan kehilangan fokus.

Namun, menutup keyboard lunak tidak akan secara otomatis membatalkan fokus elemen. Saya yakin 99,99% pengembang Android menginginkannya (dan bahwa penanganan fokus pada EditTextelemen kurang dari rawa pada umumnya), tetapi sampai saat ini belum ada fungsi bawaan untuk itu. Metode termudah yang saya temukan untuk mengatasi hal ini, jika perlu, adalah memperluas EditTextsesuatu seperti ini:

public class EditTextCloseEvent extends AppCompatEditText {

    public EditTextCloseEvent(Context context) {
        super(context);
    }

    public EditTextCloseEvent(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditTextCloseEvent(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            for (InputFilter filter : this.getFilters()) {
                if (filter instanceof InputFilterIntRange)
                    ((InputFilterIntRange) filter).onFocusChange(this, false);
            }
        }
        return super.dispatchKeyEvent(event);
    }
}

Ini akan "mengelabui" filter untuk membersihkan input meskipun pandangan belum benar - benar kehilangan fokus. Jika pandangan terjadi kemudian kehilangan fokus sendiri, sanitasi input akan memicu lagi, tetapi tidak ada yang akan berubah karena sudah diperbaiki.

Penutupan

Wah. Itu banyak. Apa yang awalnya tampak seperti itu akan menjadi masalah yang cukup mudah dan berakhir dengan mengungkap banyak potongan vanilla Android yang jelek (setidaknya di Jawa). Dan sekali lagi, Anda hanya perlu menambahkan pendengar dan memperpanjang EditTextjika rentang Anda tidak termasuk 0 dalam beberapa cara. (Dan secara realistis, jika rentang Anda tidak termasuk 0 tetapi mulai dari 1 atau -1, Anda juga tidak akan mengalami masalah.)

Sebagai catatan terakhir, ini hanya berfungsi untuk int . Tentu saja ada cara untuk mengimplementasikannya agar bekerja dengan desimal ( double, float), tetapi karena saya maupun penanya semula tidak membutuhkan hal itu, saya tidak ingin terlalu mendalam. Akan sangat mudah untuk hanya menggunakan pemfilteran pasca-penyelesaian bersama dengan baris berikut:

// Quick "fail"
if (value >= 0 && value > max) return false;
if (value >= 0 && value >= min) return true;
if (value < 0 && value < min) return false;
if (value < 0 && value <= max) return true;

Anda hanya perlu mengubah dari intmenjadi float(atau double), mengizinkan penyisipan satu .(atau ,, tergantung pada negara?), Dan parse sebagai salah satu tipe desimal alih-alih sebuah int.

Itu menangani sebagian besar pekerjaan, jadi itu akan bekerja sangat mirip.

VerumCH
sumber
2
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        String prefix = dest.toString().substring(0, dstart);
        String insert = source.toString();
        String suffix = dest.toString().substring(dend);
        String input_string = prefix + insert + suffix;
        int input = Integer.parseInt(input_string);

        if (isInRange(min, max, input) || input_string.length() < String.valueOf(min).length())
            return null;
    } catch (NumberFormatException nfe) { }
    return "";
}

private boolean isInRange(int a, int b, int c) {
    return b > a ? c >= a && c <= b : c >= b && c <= a;
}
jet27
sumber
2

Contoh yang sangat sederhana di Kotlin:

import android.text.InputFilter
import android.text.Spanned

class InputFilterRange(private var range: IntRange) : InputFilter {

    override fun filter(source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int) = try {
        val input = Integer.parseInt(dest.toString() + source.toString())
        if (range.contains(input)) null else ""
    } catch (nfe: NumberFormatException) {
        ""
    }
}
Andrew
sumber
1

silakan periksa kode ini

    String pass = EditText.getText().toString(); 
    if(TextUtils.isEmpty(pass) || pass.length < [YOUR MIN LENGTH]) 
    { 
       EditText.setError("You must have x characters in your txt"); 
        return; 
    }

    //continue processing



edittext.setOnFocusChangeListener( new OnFocusChangeListener() {

       @Override
       public void onFocusChange(View v, boolean hasFocus) {
          if(hasFocus) {
           // USE your code here 
  }

GUNAKAN tautan di bawah ini untuk detail lebih lanjut tentang edittext dan filter edittext dengan pengamat teks ..

http://www.mobisoftinfotech.com/blog/android/android-edittext-setfilters-example-numeric-text-field-patterns-and-length-restriction/

itsrajesh4uguys
sumber
OP ingin memvalidasinya ketika nilainya dimasukkan. Saya pikir Anda telah memberikan solusi untuk skenario setelah nilai dimasukkan
MysticMagicϡ
Saya bukan penanya. Saya baru saja meragukan jawaban Anda, jadi saya mengklarifikasi.
MysticMagicϡ
Saya tidak ingin memeriksa jumlah karakter. Saya pikir Anda mencoba untuk memeriksa hitungan dalam kode ini: if (TextUtils.isEmpty (pass) || pass.length <[PANJANG MIN ANDA]) Saya hanya membatasi nilai misalnya nilai bulan, pengguna harus menulis nilai antara 1-12 bukan 13,14, atau dll. Jadi, 12,13,14, hingga 99 adalah 2 karakter.
mertaydin
hai @mertaydin apakah Anda mencoba dengan tautan yang saya berikan kepada Anda .. lihat contoh itu .. mungkin itulah yang Anda inginkan. itu akan menonton teks saat Anda memasukkan ..
itsrajesh4uguys
Ok terima kasih, saya akan mencoba jawaban Anda dan jawaban @Pratik Sharma.
mertaydin
1

Jika Anda hanya khawatir tentang batas maksimal maka tambahkan saja baris di bawah ini

android:maxLength="10" 

Jika Anda perlu menambahkan batas minimum, maka Anda dapat melakukannya seperti ini dalam hal ini batas minimum adalah 7. pengguna dibatasi untuk memasukkan karakter antara batas minimum dan maksimum (antara 8 dan 10)

public final static boolean isValidCellPhone(String number){
        if (number.length() < 8 || number.length() >10 ) {
            return false;
        } else {

           return android.util.Patterns.PHONE.matcher(number).matches();
        }
    }

Jika Anda juga perlu membatasi pengguna untuk memasukkan 01 di awal kemudian memodifikasi jika kondisinya seperti ini

if (!(number.startsWith("01")) || number.length() < 8 || number.length() >10 ) {  
.
.
.
}

Pada metode panggilan akhir seperti

   ....else if (!(Helper.isValidMobilePhone(textMobileNo))){
                        Helper.setEditTextError(etMobileNo,"Invalid Mobile Number");
                    }......
Faakhir
sumber
2
Itu bukan vlaue, itu panjang
portfoliobuilder
1

@Pratik Sharma

Untuk mendukung angka negatif , tambahkan kode berikut dalam metode filter :

package ir.aboy.electronicarsenal;

import android.text.InputFilter;
import android.text.Spanned;

public class InputFilterMinMax implements InputFilter {

  private int min, max;
  int input;

  InputFilterMinMax(int min, int max) {
    this.min = min;
    this.max = max;
  }

  public InputFilterMinMax(String min, String max) {
    this.min = Integer.parseInt(min);
    this.max = Integer.parseInt(max);
  }

  @Override
  public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {

      if ((dest.toString() + source.toString()).equals("-")) {
        source = "-1";
      }

      input = Integer.parseInt(dest.toString() + source.toString());
      if (isInRange(min, max, input))
        return null;

    } catch (NumberFormatException ignored) {
    }
    return "";
  }

  private boolean isInRange(int a, int b, int c) {
    return b > a ? c >= a && c <= b : c >= b && c <= a;
  }

}

Kemudian gunakan ini dari Aktivitas Anda:

findViewById(R.id.myEditText).setFilters(new InputFilter[]{ new InputFilterMinMax(1, 12)});

Atur edittext Anda dengan:

android:inputType="number|numberSigned"
Gadolf
sumber
0

// masih memiliki beberapa masalah tetapi Di sini Anda dapat menggunakan min, maks pada rentang apa pun (positif atau negatif)

// in filter calss
 @Override
 public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        try {
            // Remove the string out of destination that is to be replaced
            int input;
            String newVal = dest.toString() + source.toString();
            if (newVal.length() == 1 && newVal.charAt(0) == '-') {
                input = min; //allow
            }
            else {
                newVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend, dest.toString().length());
                // Add the new string in
                newVal = newVal.substring(0, dstart) + source.toString() + newVal.substring(dstart, newVal.length());
                input = Integer.parseInt(newVal);
            }

            //int input = Integer.parseInt(dest.toString() + source.toString());

            if (isInRange(min, max, input))
                return null;
        } catch (NumberFormatException nfe) {
        }
        return "";
    }

//also the filler must set as below: in the edit createview
// to allow enter number and backspace.
et.setFilters(new InputFilter[]{new InputFilterMinMax(min >= 10 ?  "0" : String.valueOf(min), max >-10 ? String.valueOf(max) :"0" )});



//and at same time must check range in the TextWatcher()
et.addTextChangedListener(new
 TextWatcher() {

      @Override
      public void afterTextChanged (Editable editable)
      {
         String tmpstr = et.getText().toString();
         if (!tmpstr.isEmpty() && !tmpstr.equals("-") ) {
             int datavalue = Integer.parseInt(tmpstr);
             if ( datavalue >= min || datavalue <= max) {
               // accept data ...     
             }
         }
      }
 });
CHTsai
sumber
0

Untuk menambah jawaban Pratik, berikut adalah versi yang dimodifikasi di mana pengguna dapat memasukkan min 2 digit juga, misalnya 15 hingga 100:

 import android.text.InputFilter;
 import android.text.Spanned;

public class InputFilterMinMax implements InputFilter {

    private int min, max;

    public InputFilterMinMax(int min, int max) {
        this.min = min;
        this.max = max;
    }

    public InputFilterMinMax(String min, String max) {
        this.min = Integer.parseInt(min);
        this.max = Integer.parseInt(max);
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

        try {
            if(end==1)
                min=Integer.parseInt(source.toString());
            int input = Integer.parseInt(dest.toString() + source.toString());
            if (isInRange(min, max, input))
                return null;
        } catch (NumberFormatException nfe) {
        }
        return "";
    }

    private boolean isInRange(int a, int b, int c) {

        return b > a ? c >= a && c <= b : c >= b && c <= a;
    }}

ditambahkan: if (end == 1) min = Integer.parseInt (source.toString ());

Semoga ini membantu. mohon jangan downvote tanpa alasan.

sanjeeb
sumber
0

inilah cara yang saya gunakan, ini berfungsi untuk angka negatif

Pertama, buat kelas MinMaxFIlter.java dengan kode berikut:

import android.text.InputFilter;
import android.text.Spanned;
import android.util.Log;

/**
* Created by 21 on 4/5/2016.
*/
public class MinMaxFilter implements InputFilter {

private double mIntMin, mIntMax;

public MinMaxFilter(double minValue, double maxValue) {
    this.mIntMin = minValue;
    this.mIntMax = maxValue;
}

public MinMaxFilter(String minValue, String maxValue) {
    this.mIntMin = Double.parseDouble(minValue);
    this.mIntMax = Double.parseDouble(maxValue);
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        Boolean isNeg = false;
        String provi = dest.toString() + source.toString();
        if("-".equals(provi.substring(0,1))){
            if(provi.length()>1) {
                provi = provi.substring(1, provi.length());
                isNeg = true;
            }
            else{
                if("".equals(source)){
                    return null;
                }
                return "-";
            }
        }

        double input = Double.parseDouble(provi); 
        if(isNeg){input = input * (-1);}

        if (isInRange(mIntMin, mIntMax, input)) {
            return null;
        }
    } catch (Exception nfe) {}
    return "";
}

private boolean isInRange(double a, double b, double c) {
    if((c>=a && c<=b)){
        return true;
    }
    else{
        return false;
    }
}
}

Lalu, buat dan atur filter Anda ke edittext Anda seperti ini:

EditText edittext = new EditText(context);
editext.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
eInt.setFilters(new InputFilter[]{new MinMaxFilter(min, max)});
maloromano
sumber
0

ini kode saya maks = 100, min = 0

xml

<TextView
                    android:id="@+id/txt_Mass_smallWork"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textColor="#000"
                    android:textSize="20sp"
                    android:textStyle="bold" />

Jawa

EditText ed = findViewById(R.id.txt_Mass_smallWork);
    ed.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {`

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            if(!charSequence.equals("")) {
                int massValue = Integer.parseInt(charSequence.toString());
                if (massValue > 10) {
                    ed.setFilters(new InputFilter[]{new InputFilter.LengthFilter(2)});
                } else {
                    ed.setFilters(new InputFilter[]{new InputFilter.LengthFilter(3)});
                }
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {

        }
    });
Hoàng
sumber
0

Anda dapat melakukan ini dengan InputFilter. Tampaknya hanya ada Antarmuka Filter Input yang dapat Anda gunakan. Sebelum Anda melakukannya dengan cara yang mengganggu, buat Kelas baru yang memperluas filter Input, Anda dapat menggunakan pintasan ini dengan instantiasi Antarmuka kelas dalam.

Karena itu, lakukan saja ini:

EditText subTargetTime = (EditText) findViewById(R.id.my_time);
subTargetTime.setFilters( new InputFilter[] {
                new InputFilter() {
                    @Override
                    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
                        int t = Integer.parseInt(source.toString());
                        if(t <8) { t = 8; }
                        return t+"";

                    }
                }
        });

Dalam contoh ini saya memeriksa apakah nilai EditText lebih besar dari 8. Jika tidak diatur ke 8. Jadi, Anda perlu membuat min max atau logika filter apa pun sendiri. Tetapi setidaknya Anda dapat menulis logika filter dengan cukup rapi dan pendek langsung ke EditText.

Semoga ini membantu

Christopher-Robin Fey Feysenbe
sumber
0

Untuk menentukan nilai minimum EditText, saya menggunakan ini:

if (message.trim().length() >= 1 && message.trim().length() <= 12) {
  // do stuf
} else {
  // Too short or too long
}
Bonne Bogaert
sumber
0

@ Patrik kode punya ide bagus tapi dengan banyak bug. @Zac dan @Anthony B (solusi angka negatif) telah menyelesaikan beberapa di antaranya, tetapi kode @ Zac masih memiliki 3 bug utama:

1. Jika pengguna menghapus semua entri dalam EditText, tidak mungkin untuk mengetikkan angka apa pun lagi. Tentu saja ini dapat dikontrol menggunakan EditText yang diubah pendengar pada setiap bidang, tetapi itu akan menghapus keindahan menggunakan kelas InputFilter yang umum untuk masing-masing EditText di aplikasi Anda.

2. Apakah @ Guernee4 mengatakan, jika misalnya min = 3, tidak mungkin untuk mengetikkan angka yang dimulai dengan 1.

3. Jika misalnya min = 0, Anda dapat mengetik memiliki banyak nol yang Anda inginkan, sehingga hasilnya tidak elegan. Atau juga, jika berapapun nilainya min, pengguna dapat menempatkan kursor dalam ukuran kiri dari angka pertama, sebuah tempat sekelompok nol di depan ke kiri, juga tidak elegan.

Saya menemukan sedikit perubahan pada kode @ Zac untuk menyelesaikan 3 bug ini. Mengenai bug # 3, saya masih belum dapat sepenuhnya menghapus semua nol di depan; Itu selalu bisa menjadi satu, tetapi 00, 01, 0100 dll dalam kasus itu, lebih elegan dan valid bahwa 000000, 001, 000100, dll. Dll

Ini kodenya:

@Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        try {

            // Using @Zac's initial solution
            String lastVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend);
            String newVal = lastVal.substring(0, dstart) + source.toString() + lastVal.substring(dstart);
            int input = Integer.parseInt(newVal);

            // To avoid deleting all numbers and avoid @Guerneen4's case
            if (input < min && lastVal.equals("")) return String.valueOf(min);

            // Normal min, max check
            if (isInRange(min, max, input)) {

                // To avoid more than two leading zeros to the left
                String lastDest = dest.toString();
                String checkStr = lastDest.replaceFirst("^0+(?!$)", "");
                if (checkStr.length() < lastDest.length()) return "";

                return null;
            }
        } catch (NumberFormatException ignored) {}
        return "";
    }

Semoga harimu menyenangkan!

nnyerges
sumber
-1

Inilah jawaban saya atas jawaban Pratik Sharma untuk Kotlindan Doublejika ada yang membutuhkannya

class InputFilterMinMax : InputFilter {

private var min: Double = MIN_LIMIT
private var max: Double = MIN_LIMIT

constructor(min: Int, max: Int) {
    this.min = min.toDouble()
    this.max = max.toDouble()
}

constructor(min: String, max: String) {
    this.min = min.toDouble()
    this.max = max.toDouble()
}

constructor(min: Double, max: Double) {
    this.min = min
    this.max = max
}

override fun filter(
    source: CharSequence,
    start: Int,
    end: Int,
    dest: Spanned,
    dstart: Int,
    dend: Int
): CharSequence? {
    try {
        val input = (dest.toString() + source.toString()).toDouble()
        if (isInRange(min, max, input))
            return null
    } catch (nfe: NumberFormatException) {
        Timber.e(nfe)
    }

    return ""
}

private fun isInRange(a: Double, b: Double, c: Double): Boolean {
    return if (b > a) c in a..b else c in b..a
}
}
Varun Barve
sumber
Filter input ini salah, ia mengabaikan awal, akhir, dstart, indeks dend teks, jadi jika Anda mengubah teks edit dengan memasukkan karakter di tengah itu tidak akan berfungsi dengan benar
Radu