java - studio - ¿Tienes un onClick desactivado?
disabled button android studio (10)
Cuando está deshabilitado, setEnabled(false)
, estos escuchas no funcionarán.
Intente de esta manera: no lo deshabilite, use setOnCheckedChangeListener
y setOnCheckedChangeListener
con su entrada completada allí:
utilizar setOnCheckedChangeListener
switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (!isEntryFilled) {
buttonView.setChecked(false);
// your alert dialog
} else {
}
}
});
esto lo volverá a marcar y desactivará su alerta, hasta que se cumpla isEntryFilled
.
EDITAR
O en lugar de setEnabled(false)
, use setClickable(false)
o android:clickable="false"
ya que los documentos dicen que setClickable()
está vinculado a eventos de clic .
y en lugar de OnClickListener
, intente OnTouchListener
. Registrará su toque instantáneo (e ignorará su toque instantáneo), ya que un clic consiste en abajo + arriba.
switch.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (!isEntryFilled) {
buttonView.setChecked(false);
// your alert dialog
}
return false;
}
});
luego, en otro lugar, donde verifique que haya isEntryFilled
, reactive su conmutador con switch.setClickable(true)
Quiero poder responder a un evento de clic en un interruptor deshabilitado, ¿es posible?
Tengo un interruptor que no está habilitado hasta que el usuario llena alguna información, por lo que se ve así:
Quiero pedirle al usuario que complete la información si hace clic en el interruptor deshabilitado con un cuadro de diálogo, así:
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();
}
}
});
Sin embargo, el onClick()
no se activa cuando hago clic en el interruptor deshabilitado, entonces, ¿cómo obtengo cuando el usuario hace clic en él?
Deje que la View
intercepte ClickEvent
s o TouchEvent
s, cuando se detecte, compruebe si la View
receptora está desactivada y haga lo que tenga que hacer.
Editar
" no funciona cuando está deshabilitado? "
pruebe estos códigos, uso LinearLayout
para facilitar la alineación. Pero en general debería darte un ejemplo.
este es un ejemplo completo
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])));
}
}
Ahora, en el que haga clic se comprobará que es verdadero, ese es el niño, ahora, cuando se verifica que es verdadero, puede hacer algo como esto.
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
para el evento de clic, no intento esto, pero simplemente puede hacer View.performClick()
o poner su diálogo en la clase ViewGroup
y llamarlo
en realidad, podría usar View..getClipBounds()
para salvarse de la matriz int
Desde el código fuente de 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;
}
el indicador habilitado garantiza que los eventos UnhandledEvents se consuman, sin embargo, no se transmiten a los oyentes, por lo que se omiten todos los códigos posibles. Por lo tanto, no es posible escuchar eventos en una vista deshabilitada.
Dicho esto, tus opciones son,
- Cambie el estilo para imitar el de una vista deshabilitada como se menciona here , y luego agregue la funcionalidad requerida.
- Agregue una vista invisible de superposición para realizar la funcionalidad requerida que puede configurar como Desactivada una vez que la vista debe estar habilitada.
- Use algo aparte de habilitado, (podría establecer
setClickable(false)
y consumir eventos táctiles)
Establezca los interruptores deshabilitados en el escucha de clic para cambiar los oyentes de los otros interruptores. Por ejemplo:
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();
}
}
});
}
}
Intente configurar setFocusable(false)
y setEnabled(true)
en su conmutador. De esa manera, los eventos de clics se activarán mientras el interruptor aún esté "deshabilitado". Tomado de esta respuesta .
Podría colocar una View
transparente sobre el Switch
y cambiar su estado habilitado frente al Interruptor, y mostrar el mensaje cuando se haga clic en esta View
superpuesta.
Puede configurar onTouchListener
y reaccionar a la referencia boolean
(por ejemplo, isToggleEnable
) con respecto a las acciones anteriores del usuario:
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;
}
});
Puede hacer esto de una manera diferente. Dar un diseño de raíz para alternar el botón con la misma anchura y altura que el botón de alternar
<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>
Cuando deshabilita el botón, haga que el botón no se pueda enfocar y hacer clic. Luego, el sistema operativo entregará la funcionalidad táctil a rootlayout. En la lista de clics del diseño raíz, podemos escribir la lógica de clic cuando el botón no está habilitado.
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
}
});
}
}
Cuando habilite el botón, haga que el botón se pueda hacer clic y se pueda usar.
//enabling button
button.setEnabled(true);
button.setClickable(true);
button.setFocusableInTouchMode(true);
button.setFocusable(true);
Supongo que ha deshabilitado el conmutador utilizando switch.setEnabled (false). Si es así, el evento onclick no se activará. Si aún desea manejar una acción de clic cuando el interruptor está deshabilitado, puede usar .setOnTouchListener () ...
Sin embargo, lo mejor es usar .setOnCheckedChangeListener () y mantener el interruptor habilitado. Básicamente, cuando se llama a onCheckChanged (), puede abrir el cuadro de diálogo si el valor del interruptor está activado y cuando el usuario hace clic en Aceptar, el interruptor vuelve a estar predeterminado.
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();
}
}
});
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
}