onClick有禁用吗?

时间:2016-08-07 21:26:18

标签: java android string button disabled-control

我希望能够对已停用的交换机上的点击事件做出响应,这可能吗?

我有一个开关,在用户填写一些信息之前没有启用,所以它看起来像这样:

enter image description here

我想提示用户填写信息,如果他们点击禁用的开关并带有对话框,如下所示:

 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()不会被触发,那么当用户点击它时我该怎么办?

10 个答案:

答案 0 :(得分:13)

您可以在View的顶部放置一个透明的Switch,并在Switch的对面切换其启用状态,并在点击此View时显示该消息。

答案 1 :(得分:9)

来自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但不传递给侦听器,从而绕过所有可能的代码。因此无法在禁用的视图上侦听事件。

那就是说,你的选择是,

  1. 更改样式以模仿已提及here的已禁用视图的样式,然后添加所需的功能。
  2. 添加覆盖不可见视图以执行所需的功能,一旦启用视图,您就可以将其设置为Gone。
  3. 使用除启用之外的其他内容(您可以setClickable(false)并使用触摸事件)

答案 2 :(得分:8)

您可以针对用户之前的操作设置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 :(得分:5)

当它被禁用时,setEnabled(false),这些听众无法工作。

尝试这种方式:不要禁用它,使用setOnCheckedChangeListener并检查那里填写的is-entry:

使用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",因为文档说setClickable()点击事件相关联。

而不是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)

重新启动您的开关

答案 4 :(得分:5)

尝试在您的交换机上设置setFocusable(false)setEnabled(true)。这样,当交换机仍然被禁用时,将触发点击事件"。取自this answer

答案 5 :(得分:4)

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
    }

答案 6 :(得分:4)

让父View拦截ClickEventTouchEvent,当检测到检查接收View是否被禁用时,并执行您必须执行的操作。< / p>

修改

禁用后无效?

尝试这些代码,我使用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

对于点击事件我不是试试这个,但你可以做View.performClick()或将你的对话放在ViewGroup课程中并称之为

实际上你可以使用View..getClipBounds()从int数组中保存自己

答案 7 :(得分:4)

在单击侦听器上设置禁用开关以更改其他开关的侦听器。例如:

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();
                        }
                    }
             });
      }
}

答案 8 :(得分:4)

我猜你已经使用switch.setEnabled(false)禁用了交换机。如果是这样,onclick事件将不会触发。如果您仍希望在禁用开关时处理单击操作,则可以使用.setOnTouchListener()...

但最好的办法是使用.setOnCheckedChangeListener()并保持启用开关。基本上当onCheckChanged()被调用时,如果开关值打开,当用户单击“确定”时,可以弹出对话框,将开关默认为关闭。

    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();
            }
        }
    });

答案 9 :(得分:3)

您可以采用不同的方式执行此操作,为切换按钮设置根布局,切换按钮的宽度和高度相同

<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>

当您禁用按钮时,使按钮不可点击并可点击。然后操作系统将触摸功能切换到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);