আমি পাঠ্য প্রহরীকে ট্রিগার না করে কীভাবে সম্পাদনা পাঠ্য পাঠ্য পরিবর্তন করতে পারি?


104

আমার এতে EditTextগ্রাহক পাঠ্য প্রহরী সহ একটি ক্ষেত্র রয়েছে। কোডের একটি অংশে আমার ব্যবহার করা সম্পাদনা পাঠের মান পরিবর্তন করতে হবে .setText("whatever")

সমস্যাটি হ'ল আমি পরিবর্তন করার সাথে সাথেই afterTextChangedপদ্ধতিটি কল হয়ে যায় যা একটি অসীম লুপ তৈরি করে। পাঠ্য পরিবর্তনের পরে পাঠ্যটিকে ট্রিগার না করে কীভাবে পরিবর্তন করব?

আমার পরবর্তী পাঠ্য পদ্ধতিতে পাঠ্যটি দরকার তাই এটি মুছে ফেলার পরামর্শ দিবেন না TextWatcher

উত্তর:


70

আপনি পর্যবেক্ষকটিকে নিবন্ধভুক্ত করতে পারেন এবং তারপরে এটি পুনরায় নিবন্ধন করতে পারেন।

বিকল্পভাবে, আপনি একটি পতাকা সেট করতে পারেন যাতে আপনার পাঠক নিজেই যখন পাঠ্যটি নিজেই পরিবর্তন করেছেন (এবং তাই এটি এড়ানো উচিত) knows


আপনার ইঙ্গিতটি আমার পক্ষে যথেষ্ট। আসলে আমি শ্রোতাদের অনারিউমিতে নিবন্ধন করছিলাম তবে অনপজ () এ ডি-নিবন্ধন করছিলাম না, তাই এটি একাধিকবার কল করেছিল।
স্মিত

কারও কি এটি ব্যাখ্যা করা যায়? প্রযুক্তিগতভাবে, আমি অ্যান্ড্রয়েডে নতুন এসেছি, আরও বিস্তারিত প্লিজ দরকার, ধন্যবাদ।
বুদি মুলিও

116

সংক্ষিপ্ত উত্তর

ব্যবহারকারী এবং প্রোগ্রামের ট্রিগার হওয়া ইভেন্টগুলির মধ্যে পার্থক্য করার জন্য বর্তমানে কোন ভিউয়ের ফোকাস রয়েছে তা আপনি পরীক্ষা করতে পারেন।

EditText myEditText = (EditText) findViewById(R.id.myEditText);

myEditText.addTextChangedListener(new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        if (myEditText.hasFocus()) {
            // is only executed if the EditText was directly changed by the user
        }
    }

    //...
});

দীর্ঘ উত্তর

সংক্ষিপ্ত উত্তর অতিরিক্ত হিসাবে: যদি myEditTextইতিমধ্যে ফোকাস যখন আপনি প্রোগ্রামের মাধ্যমে আপনি অন্য যে পাঠ্য কল করা উচিত পরিবর্তন হয়েছে clearFocus(), তাহলে আপনি কল setText(...)এবং ফোকাস আপনি পরে পুনরায় অনুরোধ। এটি একটি ইউটিলিটি ফাংশনে রাখা ভাল ধারণা হবে:

void updateText(EditText editText, String text) {
    boolean focussed = editText.hasFocus();
    if (focussed) {
        editText.clearFocus();
    }
    editText.setText(text);
    if (focussed) {
        editText.requestFocus();
    }
}

কোটলিনের জন্য:

যেহেতু কোটলিন এক্সটেনশন ফাংশনকে সমর্থন করে আপনার ইউটিলিটি ফাংশনটি দেখতে এরকম হতে পারে:

fun EditText.updateText(text: String) {
    val focussed = hasFocus()
    if (focussed) {
        clearFocus()
    }
    setText(text)
    if (focussed) {
        requestFocus()
    }
}

খণ্ড getActivity().getCurrentFocus()এবং কোটলিনেactivity?.currentFocus
মোহাম্মদ রেজা খাহানী

@ মোহাম্মদরেজাখাহানী আরে! তোমার দরকার নেই আপনি hasFocus()সরাসরি কল করতে পারেন EditText
উইল মেন্টজেল

আদর্শ নয়। এডিটেক্সট ফোকাস থাকলেও যদি আমি ট্রিগার শ্রোতা ছাড়া সেটটেক্সট () সেট করতে চান?
জয়া প্রকাশ

31
public class MyTextWatcher implements TextWatcher {
    private EditText et;

    // Pass the EditText instance to TextWatcher by constructor
    public MyTextWatcher(EditText et) {
        this.et = et;
    }

    @Override
    public void afterTextChanged(Editable s) {
        // Unregister self before update
        et.removeTextChangedListener(this);

        // The trick to update text smoothly.
        s.replace(0, s.length(), "text");

        // Re-register self after update
        et.addTextChangedListener(this);
    }
}

ব্যবহার:

et_text.addTextChangedListener(new MyTextWatcher(et_text));

আপনি যদি সম্পাদনযোগ্য.রেজ () পরিবর্তে editText.setText () ব্যবহার করে থাকেন তবে দ্রুত পাঠ্য প্রবেশের সময় আপনি কিছুটা পিছিয়ে পড়তে পারেন ।


কেন এই নিম্নমানের ছিল? এটি আমার সমস্যার নিখুঁত সমাধান যেখানে অন্যরা কাজ করে না। আমি যুক্ত করব তবে এই সমাধানটি কাজ করার জন্য টেক্সট ওয়াচারকে সাবক্লাস করা দরকার নয়। ধন্যবাদ চান চুন হিম।
মাইকেল ফুলটন

টেক্সটওয়াচারটি নিবন্ধভুক্ত ও নিবন্ধভুক্ত করার জন্য আপনার ধারণা দুর্দান্ত কাজ করে। তবে, যখন et.setText ("") কাজ করে, s.replace (0, s.leth (), "") এটি ব্যবহার করে না।
স্টিভেস

@ স্টিভেহস 17, আপনার কোডটি কীভাবে তা আমি জানি না তবে ব্যবহারটি বেশ বিস্তারিতভাবে আপডেট করা হয়েছিল, একবার চেষ্টা করুন।
চান চুন হিম

15

ঠিক করার সহজ কৌশল ... যতক্ষণ না নতুন সম্পাদনা পাঠ্যের মান অর্জন করার জন্য আপনার যুক্তিটি আদর্শবান (যা সম্ভবত এটি হবে তবে কেবল বলা হচ্ছে)। আপনার শ্রোতার পদ্ধতিতে, বর্তমান মানটি আপনি যখন গতবারের সময়টি সংশোধন করেছেন তার চেয়ে বর্তমানের মানটি ভিন্ন হলে কেবলমাত্র সম্পাদনা পাঠ্যকে সংশোধন করুন।

যেমন,

TextWatcher tw = new TextWatcher() {
  private String lastValue = "";

  @Override
  public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
  }

  @Override
  public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
  }

  @Override
  public void afterTextChanged(Editable editable) {

    // Return value of getNewValue() must only depend
    // on the input and not previous state
    String newValue = getNewValue(editText.getText().toString());
    if (!newValue.equals(lastValue)) {
      lastValue = newValue;

      editText.setText(newValue);
    }
  }
};

1
এরপরেও পদ্ধতিটির দ্বিগুণ কল করা হবে তবে, না?
ট্রেভর হার্ট

হ্যাঁ, এ কারণেই আমি বলেছি এটি আদর্শবান হওয়া উচিত (এটি আরও স্পষ্ট করে দেওয়া উচিত ছিল) ... আদর্শ নয় তবে আপনি যদি কোনও একক পদ্ধতিতে কল করার ওভারহেড সম্পর্কে উদ্বিগ্ন থাকেন যা কোনও কাজ করে না তবে আপনাকে সত্যই কঠোরভাবে অনুকূল করতে হবে। যদি তাই হয় তবে আপনি শ্রোতাদের কল করার আগেই কোডটি সরিয়ে দেওয়ার setText()এবং পুনরায় যুক্ত করার পরে কোডটি পুনরায় সংগঠিত করতে পারেন ।
জেফ্রি ব্লাটম্যান

6

আমি সেভাবে ব্যবহার করি:

mEditText.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) {}

            @Override
            public void afterTextChanged(Editable s) {
                if (mEditText.isFocused()) { //<-- check if is focused 
                    mEditText.setTag(true);
                }
            }
        });

এবং প্রতিটি বার যখন আপনার পাঠ্যক্রমক্রমে পরিবর্তন করা দরকার, প্রথমে ফোকাসটি সাফ করুন

mEditText.clearFocus();
mEditText.setText(lastAddress.complement);

5

এর সাধারণ সমাধান পেতে আপনি কোটলিন ডিএসএল সিনট্যাক্স ব্যবহার করতে পারেন:

fun TextView.applyWithDisabledTextWatcher(textWatcher: TextWatcher, codeBlock: TextView.() -> Unit) {
    this.removeTextChangedListener(textWatcher)
    codeBlock()
    this.addTextChangedListener(textWatcher)
}

এবং আপনার টেক্সট ওয়াচারের ভিতরে আপনি এটি ব্যবহার করতে পারেন:

editText.applyWithDisabledTextWatcher(this) {
    text = formField.name
}

অনেক ক্লিনার কোটলিন ডিএসএল দুর্দান্ত
অঞ্জল সણેণ

4

এটি আমার পক্ষে ভাল কাজ করে

EditText inputFileName; // = (EditText)findViewbyId(R.id...)
inputFileName.addTextChangedListener(new TextWatcher() {
        public void afterTextChanged(Editable s) {

            //unregistering for event in order to prevent infinity loop
            inputFileName.removeTextChangedListener(this);

            //changing input's text
            String regex = "[^a-z0-9A-Z\\s_\\-]";
            String fileName = s.toString();
            fileName = fileName.replaceAll(regex, "");
            s.replace(0, s.length(), fileName); //here is setting new text

            Log.d("tag", "----> FINAL FILE NAME: " + fileName);

            //registering back for text changes
            inputFileName.addTextChangedListener(this);
        }

        public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

        public void onTextChanged(CharSequence s, int start, int before, int count) { }
    });

3

tagদায়ের করা ফাইলটি ব্যবহার করে সমস্যাটি সহজেই সমাধান করা যায় এবং আপনাকে এডিটেক্সট ফোকাসের সাথেও ডিল করতে হবে না।

প্রোগ্রামিং হিসাবে পাঠ্য এবং ট্যাগ সেট করা হচ্ছে

editText.tag = "dummyTag"
editText.setText("whatever")
editText.tag = null

tagঅন ​​টেক্সট চেঞ্জড ইন-এর জন্য চেক করা হচ্ছে

override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
    if (editText.tag == null) {
       // your code
    }
}

3

আপনার যদি EditTextপরিবর্তনের পাঠ্যে মনোনিবেশ করার প্রয়োজন হয় তবে আপনি ফোকাসের জন্য অনুরোধ করতে পারেন:

if (getCurrentFocus() == editText) {
    editText.clearFocus();
    editText.setText("...");
    editText.requestFocus();
}

1

এই যুক্তিটি ব্যবহার করে দেখুন: আমি অসীম লুপ না গিয়েই টেক্সট ("") সেট করতে চেয়েছিলাম এবং এই কোডটি আমার পক্ষে কাজ করে। আমি আশা করি আপনি আপনার প্রয়োজনীয়তা মাপসই এটি পরিবর্তন করতে পারেন

        final EditText text= (EditText)findViewById(R.id.text);
        text.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) {

        }
        @Override
        public void afterTextChanged(Editable s) {
            if(s.toString().isEmpty())return;
            text.setText("");
            //your code
        }
    });

1

এখানে এমন একটি সহজ শ্রেণি রয়েছে যা পরিবর্তনগুলি ঘটে যাওয়ার সাথে সাথে দেখতে চাইলে সাধারন ক্ষেত্রে টেক্সট ওয়াচারের চেয়ে সহজ ইন্টারফেস সরবরাহ করে। এটি ওপি অনুরোধ হিসাবে পরবর্তী পরিবর্তনকে উপেক্ষা করার অনুমতি দেয়।

public class EditTexts {
    public final static class EditTextChangeListener implements TextWatcher {
        private final Consumer<String> onEditTextChanged;
        private boolean ignoreNextChange = false;
        public EditTextChangeListener(Consumer<String> onEditTextChanged){
            this.onEditTextChanged = onEditTextChanged;
        }
        public void ignoreNextChange(){
            ignoreNextChange = true;
        }
        @Override public void beforeTextChanged(CharSequence __, int ___, int ____, int _____) { }
        @Override public void onTextChanged(CharSequence __, int ___, int ____, int _____) { }
        @Override public void afterTextChanged(Editable s) {
            if (ignoreNextChange){
                ignoreNextChange = false;
            } else {
                onEditTextChanged.accept(s.toString());
            }
        }
    }
}

এটি এর মতো ব্যবহার করুন:

EditTexts.EditTextChangeListener listener = new EditTexts.EditTextChangeListener(s -> doSomethingWithString(s));
editText.addTextChangedListener(listener);

যখনই আপনি editTextপুনরাবৃত্তি সম্পাদনাগুলির একটি ক্যাসকেড তৈরি না করে এর সামগ্রীগুলি পরিবর্তন করতে চান, এটি করুন:

listener.ignoreNextChange();
editText.setText("whatever"); // this won't trigger the listener

0

আমার রূপ:

public class CustomEditText extends AppCompatEditText{
    TextWatcher l;

    public CustomEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public void setOnTextChangeListener(TextWatcher l) {
        try {
            removeTextChangedListener(this.l);
        } catch (Throwable e) {}
        addTextChangedListener(l);
        this.l = l;
    }

    public void setNewText(CharSequence s) {
        final TextWatcher l = this.l;
        setOnTextChangeListener(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) {

            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
        setText(s);
        post(new Runnable() {
            @Override
            public void run() {
                setOnTextChangeListener(l);
            }
        });
    }


}

শ্রোতাদের শুধুমাত্র সেটঅনটেক্সট চ্যাঞ্জলিস্টেনার () ব্যবহার করে সেট করুন এবং কেবল সেটটনেটেক্সট ব্যবহার করে পাঠ্য সেট করুন (আমি সেটটেক্সটকে ওভাররাইড করতে চেয়েছিলাম, তবে এটি চূড়ান্ত)


0

আমি একটি বিমূর্ত শ্রেণি তৈরি করেছি যা একটি পাঠ্য ওয়াচচারের মাধ্যমে সম্পাদনা পাঠ্য সংশোধন করার সময় চক্রের সমস্যাটি প্রশমিত করে।

/**
 * An extension of TextWatcher which stops further callbacks being called as a result of a change
 * happening within the callbacks themselves.
 */
public abstract class EditableTextWatcher implements TextWatcher {

    private boolean editing;

    @Override
    public final void beforeTextChanged(CharSequence s, int start, int count, int after) {
        if (editing)
            return;

        editing = true;
        try {
            beforeTextChange(s, start, count, after);
        } finally {
            editing = false;
        }
    }

    abstract void beforeTextChange(CharSequence s, int start, int count, int after);

    @Override
    public final void onTextChanged(CharSequence s, int start, int before, int count) {
    if (editing)
        return;

        editing = true;
        try {
            onTextChange(s, start, before, count);
        } finally {
            editing = false;
        }
    }

    abstract void onTextChange(CharSequence s, int start, int before, int count);

    @Override
    public final void afterTextChanged(Editable s) {
        if (editing)
            return;

        editing = true;
        try {
            afterTextChange(s);
        } finally {
            editing = false;
        }
    }    

    public boolean isEditing() {
        return editing;
    }

    abstract void afterTextChange(Editable s);
}

0

খুব সহজ, এই পদ্ধতিটি সহ পাঠ্য সেট করুন

void updateText(EditText et, String text) {
   if (!et.getText().toString().equals(text))
       et.setText(text);
}

-2

আপনার পাঠ্য পরিবর্তনগুলির বাস্তবায়ন স্থিতিশীল এবং কোনও পরিবর্তন প্রয়োজন না হলে পাঠ্য পরিবর্তন করবেন না তা নিশ্চিত করা উচিত। সাধারণত এটি এমন কোনও বিষয়বস্তু হবে যা ইতিমধ্যে একবার পর্যবেক্ষণকারীদের মাধ্যমে হয়েছিল।

সর্বাধিক সাধারণ ভুল হ'ল পাঠ্যটি আসলে পরিবর্তন না হলেও সম্পর্কিত এডিটেক্সট বা সম্পাদনাযোগ্যতে একটি নতুন পাঠ্য সেট করা।

সর্বোপরি, আপনি যদি কিছু নির্দিষ্ট দৃশ্যের পরিবর্তে সম্পাদনাযোগ্যতে আপনার পরিবর্তনগুলি করেন তবে আপনি সহজেই আপনার প্রহরীকে পুনরায় প্রত্যাখ্যান করতে পারেন এবং এটির ফলাফলটি আপনি চান তা নিশ্চিত করতে আপনি এটি কয়েকটি ইউনিট পরীক্ষার সাথে পৃথক করে পরীক্ষা করতে পারেন।

যেহেতু সম্পাদনাযোগ্য একটি ইন্টারফেস তাই আপনি এটির একটি ডামি বাস্তবায়নও ব্যবহার করতে পারেন যা কোনও রানটাইম এক্সসেপশন নিক্ষেপ করে যদি এর কোনও পদ্ধতি বলা হয় যা স্থিতিশীল হওয়া উচিত এমন বিষয়বস্তু পরীক্ষা করার সময় এর বিষয়বস্তু পরিবর্তন করার চেষ্টা করে।


-2

জিনিসটি করার আমার উপায়:

লেখার বিভাগে

        EditText e_q;

        e_q = (EditText) parentView.findViewWithTag("Bla" + i);

        int id=e_q.getId();
        e_q.setId(-1);
        e_q.setText("abcd...");
        e_q.setId(id);

আপনি সব

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

        int id = view.getId();
        if(id==-1)return;

        ....

যাইহোক কাজ করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.