Подтвердить что ты не робот

У вас отключен onClick?

Я хочу иметь возможность реагировать на событие щелчка на отключенном коммутаторе, возможно ли это?

У меня есть переключатель, который не включен, пока пользователь не заполнит какую-либо информацию, поэтому он выглядит так:

введите описание изображения здесь

Я хочу пригласить пользователя заполнить эту информацию, если они нажмут на отключенный переключатель с диалоговым окном, например:

 mySwitch.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (!userInfo.isFilled){
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle("Fill out info first!")
                        .setMessage("You must first fill out info before turning on this featurel")
                        .setNeutralButton("Okay", null)
                        .show();
            }
        }
    });

Однако onClick() не запускается, когда я нажимаю на отключенный переключатель, так как я могу получить, когда пользователь нажимает на него?

4b9b3361

Ответ 1

Вы можете поместить прозрачный View поверх Switch и переключить его включенное состояние напротив коммутатора и показать сообщение при нажатии на этот наложенный View.

Ответ 2

Вы можете установить onTouchListener и отредактировать ссылку boolean (например, isToggleEnable) относительно предыдущих действий пользователя:

 mySwitch.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(!isToggleEnable){
                //Taost here
                }
                //If isToggleEnable = false on return OnClickListener won't be called
                return isToggleEnable; 
            }
        });

Ответ 3

Из View.java исходный код,

public boolean dispatchTouchEvent(MotionEvent event) {
    // If the event should be handled by accessibility focus first.
    if (event.isTargetAccessibilityFocus()) {
        // We don't have focus or no virtual descendant has it, do not handle the event.
        if (!isAccessibilityFocusedViewOrHost()) {
            return false;
        }
        // We have focus and got the event, then use normal event dispatch.
        event.setTargetAccessibilityFocus(false);
    }

    boolean result = false;

    if (mInputEventConsistencyVerifier != null) {
        mInputEventConsistencyVerifier.onTouchEvent(event, 0);
    }

    final int actionMasked = event.getActionMasked();
    if (actionMasked == MotionEvent.ACTION_DOWN) {
        // Defensive cleanup for new gesture
        stopNestedScroll();
    }

    if (onFilterTouchEventForSecurity(event)) {
        //noinspection SimplifiableIfStatement
        ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnTouchListener != null
                && (mViewFlags & ENABLED_MASK) == ENABLED
                && li.mOnTouchListener.onTouch(this, event)) {
            result = true;
        }

        if (!result && onTouchEvent(event)) {
            result = true;
        }
    }

    if (!result && mInputEventConsistencyVerifier != null) {
        mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
    }

    // Clean up after nested scrolls if this is the end of a gesture;
    // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
    // of the gesture.
    if (actionMasked == MotionEvent.ACTION_UP ||
            actionMasked == MotionEvent.ACTION_CANCEL ||
            (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
        stopNestedScroll();
    }

    return result;
}

флаг enabled гарантирует, что UnhandledEvents потребляется, но не передается вместе с прослушивателями, тем самым минуя весь ваш возможный код. Таким образом, невозможно прослушать события в отключенном виде.

Тем не менее, ваши варианты:

  • Измените стиль, чтобы имитировать отключенное представление, как указано здесь, а затем добавьте необходимые функции.
  • Добавьте оверлейное невидимое представление для выполнения необходимых функций, которые вы можете установить в Gone после включения представления.
  • Используйте что-то отдельно от включенного (вы можете setClickable(false) и использовать события касания)

Ответ 4

Попробуйте установить setFocusable(false) и setEnabled(true) на свой коммутатор. Таким образом, события щелчка будут запущены, пока переключатель все еще будет отключен. Взято из этого ответа.

Ответ 5

Когда он отключен, setEnabled(false), эти слушатели не будут работать.

Попробуйте так: не отключайте его, используйте setOnCheckedChangeListener и проверяйте его заполнение:

использовать setOnCheckedChangeListener

    switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (!isEntryFilled) {
                buttonView.setChecked(false);
                // your alert dialog
            } else {
            }
        }
    });

это снова проверяет его на выключение и выдает ваше предупреждение, пока не будет выполнено isEntryFilled.

ИЗМЕНИТЬ

ИЛИ вместо setEnabled(false) используйте setClickable(false) или android:clickable="false", так как docs говорят, что setClickable() привязан к событиям click-events.

и вместо OnClickListener попробуйте OnTouchListener. Он зарегистрирует ваше нажатие на касание (и игнорирует ваше касание), так как щелчок состоит из вниз + вверх.

    switch.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (!isEntryFilled) {
                buttonView.setChecked(false);
                // your alert dialog
            }
            return false;
        }
    });

затем в другом месте, где вы проверяете isEntryFilled, активируйте свой переключатель с помощью switch.setClickable(true)

Ответ 6

mySwitch.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
                if (isClick()){
                   //Your Valid Code
                }else{
                  //Make our switch to false
                  new AlertDialog.Builder(MainActivity.this)
                           .setTitle("Fill out info first!")
                           .setMessage("You must first fill out info before turning on this featurel")
                            .setNeutralButton("Okay", null)
                            .show();
                   }
                }
});

    public Boolean isClick(){
         //check condition that user fill details or not
         //if yes then return true
         // else return false
    }

Ответ 7

Пусть Parent View перехватывает ClickEvent или TouchEvent s, когда его обнаружение проверяет, отключен ли прием View, и выполняйте то, что вам нужно сделать.

Edit

"он не работает при отключении?"

попробуйте эти коды, я использую LinearLayout для легкого выбора. но в целом он должен дать вам пример

это полный пример

XML

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="70dp"
android:background="#273746">   

<FrameLayout
    android:layout_width="match_parent"        
    android:id="@+id/ass"
    android:background="@drawable/abc_popup_background_mtrl_mult"
    android:layout_height="match_parent">
</FrameLayout>

MainActivity onCreate

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_entry_screen);
    FrameLayout fl = (FrameLayout)findViewById(R.id.ass);
    Test t = new Test(this);
    FrameLayout.LayoutParams lp = (LayoutParams) fl.getLayoutParams();
    lp.height = LayoutParams.MATCH_PARENT;
    lp.width = LayoutParams.MATCH_PARENT;
    t.setOrientation(LinearLayout.VERTICAL);
    t.setLayoutParams(lp);
    fl.addView(t);
    t.setBackgroundColor(Color.YELLOW);
    Button b = new Button(this);
    b.setText("patricia");
    t.addView(b);
     b = new Button(this);
    b.setText("monica");
    t.addView(b);

    b = new Button(this);
    b.setText("rebecca");
    t.addView(b);

}

Test.java

public class Test extends LinearLayout {

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

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    StringBuilder sb = new StringBuilder();
    sb.append("intercept \n\r");
    int x = (int)event.getX(),
            y= (int)event.getY();

    for(int i =0; i< getChildCount(); i++){
        int[] pos = new int[]{getChildAt(i).getLeft(),getChildAt(i).getTop(),
                getChildAt(i).getMeasuredWidth(),
                getChildAt(i).getMeasuredHeight()};

        sb.append(getChildAt(i).getLeft()+", ");
        sb.append(getChildAt(i).getTop()+", ");
        sb.append(getChildAt(i).getMeasuredWidth()+", ");
        sb.append(getChildAt(i).getMeasuredHeight());
        sb.append("\n\r");
        sb.append(isInBounds(pos, x, y));
        sb.append("\n\r");
    }
    sb.append("x is ");
    sb.append(x);
    sb.append("y is ");
    sb.append(y);
    Toast.makeText(getContext(),sb.toString() , Toast.LENGTH_LONG).show();
    return super.onInterceptTouchEvent(event);
}

private boolean isInBounds(int[] dimen, int x, int y){
    return ((x >= dimen[0] && x < (dimen[0] + dimen[2]))
            && (y >= dimen[1] && y < (dimen[1] + dimen[3])));
}

}

Теперь тот, который вы нажмете, будет проверяться как истинный, то есть ребенок, теперь, когда он проверяет, что он прав, вы можете сделать что-то вроде этого

View v = getchildAt(pos);
//its the one that is tapped or clicked
if(!v.isEnabled()){
    //this is the guy you want now, do what you want to do

для события click Я не пытаюсь это сделать, но вы можете просто сделать View.performClick() или поместить свой диалог в класс ViewGroup и вызвать его

на самом деле вы можете использовать View..getClipBounds() для сохранения себя из массива int

Ответ 8

Установите отключенные переключатели на прослушивателе кликов, чтобы изменить прослушиватели других переключателей. Например:

Switch s = (Switch) findViewById(R.id.SwitchID);

if (s != null) {
    s.setOnCheckedChangeListener(this);
}

/* ... */

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    Toast.makeText(this, "The Switch is " + (isChecked ? "on" : "off"),
                   Toast.LENGTH_SHORT).show();
    if(isChecked) {
        //do stuff when Switch is ON
        //this is where you set your normal state OnClickListner
    } else {
            mySwitch.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        if (!userInfo.isFilled){
                            new AlertDialog.Builder(MainActivity.this)
                            .setTitle("Fill out info first!")
                            .setMessage("You must first fill out info before turning on this featurel")
                            .setNeutralButton("Okay", null)
                            .show();
                        }
                    }
             });
      }
}

Ответ 9

Я предполагаю, что вы отключили коммутатор, используя switch.setEnabled(false). Если это так, событие onclick не будет запускаться. Если вы все еще хотите обработать действие щелчка, когда переключатель отключен, вы можете использовать .setOnTouchListener()...

Лучше всего будет использовать .setOnCheckedChangeListener() и включить включение. В основном, когда вызывается onCheckChanged(), вы можете всплывать в вашем диалоговом окне, если значение ключа включено, и когда пользователь нажимает ok, вы по умолчанию переключитесь на выключение.

    mSwitched.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {

            if (checked && !userInfo.isFilled){
                new AlertDialog.Builder(Activity.this)
                        .setTitle("Fill out info first!")
                        .setMessage("You must first fill out info before turning on this featurel")
                        .setNeutralButton("Okay", new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {

                                mSwitched.setChecked(false);
                            }
                        })
                        .show();
            }
        }
    });

Ответ 10

Вы можете сделать это по-другому. Дайте корневой макет для переключения кнопки с одинаковой шириной и высотой кнопки переключения.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <!--Root layout to toggle button with same height and width 
        of toggle button-->
   <LinearLayout
       android:layout_width="wrap_content"
       android:id="@+id/linear"
       android:layout_height="wrap_content">
    <ToggleButton
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button"
         />
   </LinearLayout>

</RelativeLayout>

Если вы отключите кнопку, сделайте эту кнопку нецелесообразной и кликабельной. Затем os передаст функциональность касания к rootlayout. В корневом списке переходов мы можем написать логику щелчка, когда кнопка не включена.

public class MainActivity extends AppCompatActivity {
    ToggleButton button;
    LinearLayout linearLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button= (ToggleButton) findViewById(R.id.button);
        linearLayout= (LinearLayout) findViewById(R.id.linear);
        //disabling button
        button.setEnabled(false);
        button.setClickable(false);
        button.setFocusableInTouchMode(false);
        button.setFocusable(false);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //write the logic here which will execute when button is enabled
            }
        });
        linearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //write the logic here which will execute when button is disabled
            }
        });
    }

}

Когда вы включаете кнопку, сделайте кнопку кликабельной и фокальной.

//enabling button
  button.setEnabled(true);
  button.setClickable(true);
  button.setFocusableInTouchMode(true);
  button.setFocusable(true);