স্যুইচ, চেকবক্সের মান ব্যবহারকারী বা প্রোগ্রামগতভাবে (ধরে রাখার মাধ্যমে) পরিবর্তিত হয়েছে কিনা তা আমি কীভাবে আলাদা করতে পারি?


110
setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // How to check whether the checkbox/switch has been checked
                // by user or it has been checked programatically ?

                if (isNotSetByUser())
                    return;
                handleSetbyUser();
            }
        });

পদ্ধতি কীভাবে প্রয়োগ করা যায় isNotSetByUser()?


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


আমি আরো সহজ এবং পরিষ্কার সমাধান আছে: দেখুন stackoverflow.com/a/41574200/3256989
ultraon

উত্তর:


157

উত্তর 2:

খুব সহজ উত্তর:

OnCheckedChangeListener এর পরিবর্তে OnClickListener ব্যবহার করুন

    someCheckBox.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {
            // you might keep a reference to the CheckBox to avoid this class cast
            boolean checked = ((CheckBox)v).isChecked();
            setSomeBoolean(checked);
        }

    });

এখন আপনি কেবল ক্লিক ইভেন্টগুলি বেছে নেবেন এবং প্রোগ্রাম্যাটিক পরিবর্তন সম্পর্কে চিন্তা করার দরকার নেই।


উত্তর 1:

আমি একটি মোড়কের ক্লাস তৈরি করেছি (সাজসজ্জার প্যাটার্নটি দেখুন) যা এই সমস্যাটি একটি এনপ্যাসুলেটেড উপায়ে পরিচালনা করে:

public class BetterCheckBox extends CheckBox {
    private CompoundButton.OnCheckedChangeListener myListener = null;
    private CheckBox myCheckBox;

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

    public BetterCheckBox(Context context, CheckBox checkBox) {
        this(context);
        this.myCheckBox = checkBox;
    }

    // assorted constructors here...    

    @Override
    public void setOnCheckedChangeListener(
        CompoundButton.OnCheckedChangeListener listener){
        if(listener != null) {
            this.myListener = listener;
        }
        myCheckBox.setOnCheckedChangeListener(listener);
    }

    public void silentlySetChecked(boolean checked){
        toggleListener(false);
        myCheckBox.setChecked(checked);
        toggleListener(true);
    }

    private void toggleListener(boolean on){
        if(on) {
            this.setOnCheckedChangeListener(myListener);
        }
        else {
            this.setOnCheckedChangeListener(null);
        }
    }
}

চেকবক্সটি এখনও এক্সএমএলে একই হিসাবে ঘোষিত হতে পারে তবে কোডে আপনার জিইউআই শুরু করার সময় এটি ব্যবহার করুন:

BetterCheckBox myCheckBox;

// later...
myCheckBox = new BetterCheckBox(context,
    (CheckBox) view.findViewById(R.id.my_check_box));

আপনি যদি শ্রোতাদের ট্রিগার না করে কোড থেকে চেক সেট করতে চান তবে myCheckBox.silentlySetChecked(someBoolean)তার পরিবর্তে কল করুন setChecked


15
একটির জন্য Switch, উত্তর 1 টি ট্যাপ এবং স্লাইড উভয় ক্ষেত্রেই কাজ করে, যেখানে উত্তর 2 কেবলমাত্র ট্যাপের ক্ষেত্রে কাজ করবে। ব্যক্তিগত পছন্দ হিসাবে, আমি আমার ক্লাসটি একটির রেফারেন্স রাখার পরিবর্তে প্রসারিত CheckBox/ বাড়িয়েছি Switch। সেভাবে আরও ক্লিনার মনে হচ্ছে (নোট করুন যে আপনি যদি এটি করেন তবে অবশ্যই আপনাকে অবশ্যই প্যাকেজটির পুরো নাম নির্দিষ্ট করতে হবে)।
হোয়েটল

1
এই অ্যানথ্রোপোমোর জন্য ধন্যবাদ, আমি কেন জানি না যে আমি এটি সম্পর্কে আগে কেন ভাবিনি, তবে আপনি আমাকে কিছু মূল্যবান সময় বাঁচিয়েছিলেন;)। চিয়ার্স!
সাইবারড্যান্ডি

আমি এ সম্পর্কে নিশ্চিত নই, তবে আপনি যদি উপাদান ডিজাইনের স্যুইচটি পেতে স্যুইচকম্প্যাট (অ্যাপকম্প্যাট ভি 7 ব্যবহার করে) প্রসারিত করেন তবে আপনি নতুন পুনরায় নকশা এবং টিংটিংয়ের ক্ষমতা শেষ করতে পারেন।
ডিএনএক্স

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

প্রথম সমাধান: আপনি যদি একটি সংক্ষিপ্ত সমাধান চান এবং সেই উইজেটটি ব্যবহার করার ইচ্ছা না রাখেন তবে পরিচিত এবং আধা-গ্রহণযোগ্য সমস্যা। দ্বিতীয় সমাধান: এই জাতীয় সম্ভাব্য প্রান্তের কেসটিকে মোকাবেলার জন্য নাল চেকটি পরিবর্তন করে। এখন আমরা দায়িত্ব অর্পণ listenerকরতে myListenerযখনই listenerনাল নয়। প্রায় সব ক্ষেত্রেই এটি কিছুই করে না, তবে আমরা যদি কোনও কারণে নতুন শ্রোতা তৈরি করি তবে তা ভাঙা হয়নি।
anthropomo

38

সম্ভবত আপনি চেক করতে পারেন isSown ()? যদি সত্য - এটির ব্যবহারকারীর চেয়ে। আমার জন্য কাজ কর.

setOnCheckedChangeListener(new OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (myCheckBox.isShown()) {// makes sure that this is shown first and user has clicked/dragged it
                  doSometing();
        }
    }
});

1
এটি কাজ করে (যার অর্থ কোনও অপ্রত্যাশিত কলব্যাক নয়) এমনকি আপনি অন স্টার্ট () বা অনরেসিউম () তে "সেটচেকড (আইস ​​চেকড) "ও কল করেন। সুতরাং এটি একটি নিখুঁত সমাধান হিসাবে বিবেচনা করা যেতে পারে।
অ্যালান ঝিলিয়াং ফেং

1
একটি সাধারণ সমাধান না বলে মনে হচ্ছে। মুহুর্তে বোতামটি দেখানো হয়েছে তবে কোড থেকে এর মান পরিবর্তন করা হয়েছে কি?
পাভেল

1
আমি এটি পাই না, কীভাবে 'ইসশাউন ()' ব্যবহারকারীর ক্রিয়া এবং প্রোগ্রাম্যাটিক পরিবর্তনগুলির মধ্যে পার্থক্য রাখে? যেমন এটি কীভাবে বলতে পারে এটি যদি 'ইসশাউন ()' সত্য হয় তবে এটি ব্যবহারকারীর পদক্ষেপ?
মুহাম্মদ রেফায়াত

1
এই সমাধানটি কেবল খুব সুনির্দিষ্ট ক্ষেত্রেই কাজ করে এবং অননুমোদিত, অ-গ্যারান্টিযুক্ত ক্রিয়াকলাপ তৈরি এবং লেআউটিং প্রক্রিয়া নির্ভর করে। ভবিষ্যতে এটি ভঙ্গ হবে না এমন কোনও গ্যারান্টি নেই এবং যদি কোনও ভিউ ইতিমধ্যে রেন্ডার করা হয় তবে এটি কাজ করে না।
ম্যানুয়েল

26

ইনসাইড onCheckedChanged()শুধু চেক ব্যবহারকারী আসলে আছে কিনা checked/uncheckedরেডিও বোতাম তারপর কাপড় না তদনুসারে নিম্নরূপ:

mMySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
 @Override
 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
   if (buttonView.isPressed()) {
       // User has clicked check box
    }
   else
    {
       //triggered due to programmatic assignment using 'setChecked()' method.   
    }
  }
});

ভাল সমাধান, ভিউটি কাস্টমাইজ করার দরকার নেই।
আজু

আমি তোমায় ভালোবাসি. : ডিডিডি
ভ্লাদ

12
ব্যবহারকারী যখন
স্যুইপিং

1
এই পদ্ধতির সর্বত্র ব্যবহার isPressedকরেও এটি খুঁজে পেয়েছে যে এটি টকব্যাক সহ নোকিয়া ডিভাইসটি মিথ্যা হিসাবে ফেরত হিসাবে কাজ করে না ।
মিখাইল

সমস্যা ছাড়াই সুইচমেটারিয়াল কাজ। ভাল সিদ্ধান্ত, ধন্যবাদ!
0000

25

আপনি শ্রোতাদের অগ্রগতিতে পরিবর্তন করার আগে এটি অপসারণ করতে পারেন এবং নীচের এসও পোস্টে উত্তর হিসাবে এটি আবার যুক্ত করতে পারেন:

https://stackoverflow.com/a/14147300/1666070

theCheck.setOnCheckedChangeListener(null);
theCheck.setChecked(false);
theCheck.setOnCheckedChangeListener(toggleButtonChangeListener);

4

চেকবক্স প্রসারিত করার চেষ্টা করুন। এরকম কিছু (সম্পূর্ণ উদাহরণ নয়):

public MyCheckBox extends CheckBox {

   private Boolean isCheckedProgramatically = false;

   public void setChecked(Boolean checked) {
       isCheckedProgramatically = true;
       super.setChecked(checked);
   }

   public Boolean isNotSetByUser() {
      return isCheckedProgramatically;
   }

}

3

আরও একটি সহজ সমাধান রয়েছে যা বেশ ভালভাবে কাজ করে। উদাহরণটি সুইচ এর জন্য।

public class BetterSwitch extends Switch {
  //Constructors here...

    private boolean mUserTriggered;

    // Use it in listener to check that listener is triggered by the user.
    public boolean isUserTriggered() {
        return mUserTriggered;
    }

    // Override this method to handle the case where user drags the switch
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean result;

        mUserTriggered = true;
        result = super.onTouchEvent(ev);
        mUserTriggered = false;

        return result;
    }

    // Override this method to handle the case where user clicks the switch
    @Override
    public boolean performClick() {
        boolean result;

        mUserTriggered = true;
        result = super.performClick();
        mUserTriggered = false;

        return result;
    }
}

2

আকর্ষণীয় প্রশ্ন। আমার জানা মতে আপনি একবার শ্রোতার সাথে থাকলে আপনি শনাক্তকারীকে কী পদক্ষেপ নিয়েছে তা সনাক্ত করতে পারবেন না, প্রসঙ্গটি যথেষ্ট নয়। আপনি যদি না সূচক হিসাবে বাহ্যিক বুলিয়ান মান ব্যবহার না করেন।

আপনি যখন "প্রোগ্রামটিমেটিক" বাক্সটি চেক করেন, প্রোগ্রামিয়ালি সম্পাদিত হয়েছিল তা বোঝাতে আগে একটি বুলিয়ান মান সেট করুন। কিছুটা এইরকম:

private boolean boxWasCheckedProgrammatically = false;

....

// Programmatic change:
boxWasCheckedProgrammatically = true;
checkBoxe.setChecked(true)

এবং আপনার শ্রোতার মধ্যে, চেকবক্সের স্থিতি পুনরায় সেট করতে ভুলবেন না:

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    if (isNotSetByUser()) {
        resetBoxCheckSource();
        return;
    }
    doSometing();
}

// in your activity:
public boolean isNotSetByUser() {
    return boxWasCheckedProgrammatically;
}

public void resetBoxCheckedSource() {
    this.boxWasCheckedProgrammatically  = false;
}

2

চেষ্টা করুন NinjaSwitch:

setChecked(boolean, true)সনাক্ত না করে স্যুইচের চেক করা রাষ্ট্রটি পরিবর্তন করার জন্য কেবল কল করুন !

public class NinjaSwitch extends SwitchCompat {

    private OnCheckedChangeListener mCheckedChangeListener;

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

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

    public NinjaSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        super.setOnCheckedChangeListener(listener);
        mCheckedChangeListener = listener;
    }

    /**
     * <p>Changes the checked state of this button.</p>
     *
     * @param checked true to check the button, false to uncheck it
     * @param isNinja true to change the state like a Ninja, makes no one knows about the change!
     */
    public void setChecked(boolean checked, boolean isNinja) {
        if (isNinja) {
            super.setOnCheckedChangeListener(null);
        }
        setChecked(checked);
        if (isNinja) {
            super.setOnCheckedChangeListener(mCheckedChangeListener);
        }
    }
}

2

যদি OnClickListenerইতিমধ্যে সেট করা হয় এবং ব্যবহার ওভাররাইট করা উচিত হবে না, !buttonView.isPressed()যেমন isNotSetByUser()

অন্যথায় সেরা রূপটি OnClickListenerপরিবর্তে ব্যবহার করা হয় OnCheckedChangeListener


বাটনভিউ.আইসপ্রেসড () একটি দুর্দান্ত সমাধান। যখন আমরা অনক্লিকলিস্টনার ব্যবহার করি তখন একটি সমস্যা হয়, যখন ব্যবহারকারী স্যুইচটিতে স্লাইড করে, আমরা কলব্যাক পাব না।
আজু

2

মূল চেকবক্সের কোনও রেফারেন্স না বজায় রাখতে গৃহীত উত্তরটি কিছুটা সরল করা যেতে পারে। এটি এটি তৈরি করে যাতে আমরা এক্সএমএলে সরাসরি SilentSwitchCompat(বা SilentCheckboxCompatআপনি যদি পছন্দ করেন) ব্যবহার করতে পারি । আমি এটিও তৈরি করেছি যাতে আপনি যদি এটি OnCheckedChangeListenerকরতে চান nullতবে আপনি এটি সেট করতে পারেন।

public class SilentSwitchCompat extends SwitchCompat {
  private OnCheckedChangeListener listener = null;

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

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

  @Override
  public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
    super.setOnCheckedChangeListener(listener);
    this.listener = listener;
  }

  /**
   * Check the {@link SilentSwitchCompat}, without calling the {@code onCheckChangeListener}.
   *
   * @param checked whether this {@link SilentSwitchCompat} should be checked or not.
   */
  public void silentlySetChecked(boolean checked) {
    OnCheckedChangeListener tmpListener = listener;
    setOnCheckedChangeListener(null);
    setChecked(checked);
    setOnCheckedChangeListener(tmpListener);
  }
}

এরপরে আপনি এটি সরাসরি আপনার এক্সএমএলে ব্যবহার করতে পারেন (দ্রষ্টব্য: আপনার পুরো প্যাকেজের নাম প্রয়োজন হবে):

<com.my.package.name.SilentCheckBox
      android:id="@+id/my_check_box"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textOff="@string/disabled"
      android:textOn="@string/enabled"/>

তারপরে আপনি ফোন করে নিঃশব্দে বাক্সটি চেক করতে পারেন:

SilentCheckBox mySilentCheckBox = (SilentCheckBox) findViewById(R.id.my_check_box)
mySilentCheckBox.silentlySetChecked(someBoolean)

1

এখানে আমার বাস্তবায়ন

কাস্টম স্যুইচ জন্য জাভা কোড:

public class CustomSwitch extends SwitchCompat {

private OnCheckedChangeListener mListener = null;

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

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

public CustomSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
public void setOnCheckedChangeListener(@Nullable OnCheckedChangeListener listener) {
    if(listener != null && this.mListener != listener) {
        this.mListener = listener;
    }
    super.setOnCheckedChangeListener(listener);
}

public void setCheckedSilently(boolean checked){
    this.setOnCheckedChangeListener(null);
    this.setChecked(checked);
    this.setOnCheckedChangeListener(mListener);
}}

সমতুল্য কোটলিন কোড:

class CustomSwitch : SwitchCompat {

private var mListener: CompoundButton.OnCheckedChangeListener? = null

constructor(context: Context) : super(context) {}

constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}

constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}

override fun setOnCheckedChangeListener(@Nullable listener: CompoundButton.OnCheckedChangeListener?) {
    if (listener != null && this.mListener != listener) {
        this.mListener = listener
    }
    super.setOnCheckedChangeListener(listener)
}

fun setCheckedSilently(checked: Boolean) {
    this.setOnCheckedChangeListener(null)
    this.isChecked = checked
    this.setOnCheckedChangeListener(mListener)
}}

শ্রোতার ব্যবহার ট্রিগার না করে স্যুইচ স্থিতি পরিবর্তন করতে:

swSelection.setCheckedSilently(contact.isSelected)

আপনি সাধারণত রাষ্ট্রের পরিবর্তনগুলি নিরীক্ষণ করতে পারেন:

swSelection.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
   @Override
   public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
      // Do something
   }       
 });

কোটলিনে:

 swSelection.setOnCheckedChangeListener{buttonView, isChecked -> run {
            contact.isSelected = isChecked
        }}

1

কোটলিন এক্সটেনশন ফাংশন সহ আমার বৈকল্পিক:

fun CheckBox.setCheckedSilently(isChecked: Boolean, onCheckedChangeListener: CompoundButton.OnCheckedChangeListener) {
    if (isChecked == this.isChecked) return
    this.setOnCheckedChangeListener(null)
    this.isChecked = isChecked
    this.setOnCheckedChangeListener(onCheckedChangeListener)
}

... দুর্ভাগ্যক্রমে আমাদের প্রতিবারই চেকড চ্যাঞ্জলিস্টনার পাস করতে হবে কারণ চেকবক্স ক্লাসে এম-চেকড চেঞ্জলিস্টার ক্ষেত্রের জন্য প্রাপ্তকারী নেই ((

ব্যবহার:

checkbox.setCheckedSilently(true, myCheckboxListener)

0

একটি পরিবর্তনশীল তৈরি করুন

boolean setByUser = false;  // Initially it is set programmatically


private void notSetByUser(boolean value) {
   setByUser = value;
}
// If user has changed it will be true, else false 
private boolean isNotSetByUser() {
   return setByUser;          

}

অ্যাপ্লিকেশনটিতে আপনি যখন এটি ব্যবহারকারীর পরিবর্তে পরিবর্তন করবেন, কল করুন notSetByUser(true)যাতে এটি ব্যবহারকারীর দ্বারা সেট করা হয় না, অন্যথায় কল করুন notSetByUser(false)এটি প্রোগ্রাম দ্বারা সেট করা হয়েছে।

শেষ অবধি, আপনার ইভেন্ট শ্রোতাদের, isNotSetByUser () কল করার পরে, নিশ্চিত হয়ে নিন যে আপনি আবার এটিকে স্বাভাবিক অবস্থায় ফিরিয়ে দিয়েছেন।

আপনি যখনই ব্যবহারকারী বা প্রোগ্রামের মাধ্যমে সেই ক্রিয়াটি পরিচালনা করছেন তখনই এই পদ্ধতিটিকে কল করুন। উপযুক্ত মান সহ নটসেটবাইজার () কে কল করুন।


0

যদি ভিউটির ট্যাগ ব্যবহার না করা হয় তবে আপনি চেকবক্সটি বাড়ানোর পরিবর্তে এটি ব্যবহার করতে পারেন:

        checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                @Override
                public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
                    if (buttonView.getTag() != null) {
                        buttonView.setTag(null);
                        return;
                    }
                    //handle the checking/unchecking
                    }

প্রতিবার যখন আপনি এমন কিছু কল করেন যা চেকবক্সটি চেক / আনচেক করে, চেক / আনচেকিং করার আগে এটিকেও কল করুন:

checkbox.setTag(true);

0

আমি আরএক্সজেভার PublishSubjectসহজ সরল সাথে এক্সটেনশন তৈরি করেছি । শুধুমাত্র "অনক্লিক" ইভেন্টগুলিতে প্রতিক্রিয়া।

/**
 * Creates ClickListener and sends switch state on each click
 */
fun CompoundButton.onCheckChangedByUser(): PublishSubject<Boolean> {
    val onCheckChangedByUser: PublishSubject<Boolean> = PublishSubject.create()
    setOnClickListener {
        onCheckChangedByUser.onNext(isChecked)
    }
    return onCheckChangedByUser
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.