有一个禁用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()不会被触发,所以当用户点击它时我怎么得到?

  • 使用HashMap来映射一个String和int
  • 从网页获取文本到string
  • 在Android中将文件path转换为Uri
  • Android:如何在url.xml资源文件中存储url?
  • 在Android上的化学公式
  • Android - 使用getIdentifier()和getStringArray使用另一个string引用string数组
  • 如何正确编辑阿拉伯文string?
  • 组织Strings.xml
  • 您可以在Switch顶部放置一个透明View ,并在交换机对面切换其启用状态,并在单击此叠加View时显示消息。

    您可以设置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; } }); 

    从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; } 

    启用标志确保UnhandledEvents消耗,但不传递给监听器,从而绕过所有可能的代码。因此,无法在禁用的视图上监听事件。

    这就是说,你的select是,

    1. 将样式更改为模仿此处提及的禁用视图的样式,然后添加所需的function。
    2. 添加一个覆盖不可见的视图来执行所需的function,您可以将其设置为一旦启用视图即可。
    3. 使用除了启用的东西,(你可以setClickable(false)和消费触摸事件)

    尝试在交换机上设置setFocusable(false)setEnabled(true) 。 这样,点击事件将被激活,而交换机仍处于“禁用”状态。 从这个答案采取。

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

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

    使用setOnCheckedChangeListener

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

    这将重新检查它closures并popup您的警报,直到isEntryFilled遇到。

    编辑

    或者,而不是setEnabled(false) ,使用setClickable(false)android:clickable="false"因为文档说setClickable()绑定到点击事件

    而不是OnClickListener ,请尝试OnTouchListener 。 它会注册你的on-down-touch(并忽略你的on-up-touch),因为点击包括down + up。

      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)重新激活您的交换机

     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 } 

    让父View拦截ClickEventTouchEvent ,当它检测到检查接收View是否被禁用,并做你必须做的事情。

    编辑

    禁用时不起作用?

    尝试这些代码,我使用LinearLayout容易alignment。 但总的来说应该给你一个例子

    这是一个完整的例子

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

    在点击监听器上设置禁用开关,以更改其他交换机的监听器。 例如:

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

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

    不过最好的办法是使用.setOnCheckedChangeListener()并保持开关的启用。 基本上,当onCheckChanged()被调用时,如果开关值处于打开状态,并且当用户单击确定时,您可以popup对话框,您可以将开关默认为closures。

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

    你可以用不同的方式做到这一点,给一个根的布局切换button具有相同的宽度和高度的切换button

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

    当你禁用button时,使button不可触摸并可点击。然后os将触摸function切换到rootlayout。在根布局点击列表中,我们可以编写点击逻辑,当button没有启用

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

    当你启用button,使button可点击和focausable。

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