有一个禁用的onClick?
Posted
技术标签:
【中文标题】有一个禁用的onClick?【英文标题】:Have a disabled onClick? 【发布时间】:2016-12-13 14:38:46 【问题描述】:我希望能够响应禁用开关上的点击事件,这可能吗?
我有一个开关直到用户填写一些信息才启用,所以它看起来像这样:
如果用户单击禁用的开关并带有对话框,我想提示用户填写信息,如下所示:
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()
在我点击禁用的开关时并没有被触发,那么当用户点击它时我该如何获取呢?
【问题讨论】:
什么是lightSwitch
?它的isEnabled()
方法是自动更新的,还是需要您自己更新(即lightSwitch.setEnabled(!lightSwitch.isEnabled())
?
另外,mySwitch
是什么?请包含变量的声明。
任何回应?你检查我的代码了吗?
【参考方案1】:
您可以在Switch
上放置一个透明的View
,并在开关对面切换其启用状态,并在单击此覆盖的View
时显示消息。
【讨论】:
【参考方案2】:来自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 被消耗但不传递给侦听器,从而绕过所有可能的代码。因此无法在禁用视图上侦听事件。
也就是说,您的选择是,
-
更改样式以模仿here 中提到的禁用视图的样式,然后添加所需的功能。
添加一个覆盖不可见视图以执行您需要的功能,一旦启用该视图,您可以将其设置为 Gone。
使用除了启用之外的东西,(你可以
setClickable(false)
并使用触摸事件)
【讨论】:
我选择了选项 2,因此我不需要设置我需要禁用的所有不同控件的样式...我使用了相对布局,以便我可以将叠加层放在其他控件。这个答案帮助我创建了一个覆盖......***.com/a/33997626/2898715【参考方案3】:您可以设置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;
);
【讨论】:
【参考方案4】:当它被禁用时,setEnabled(false)
,这些监听器将无法工作。
试试这个方法:不要禁用它,使用 setOnCheckedChangeListener
并检查你的 is-entry-fill 在那里:
使用setOnCheckedChangeListener
switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
if (!isEntryFilled)
buttonView.setChecked(false);
// your alert dialog
else
);
这将重新检查它以关闭并弹出您的警报,直到遇到isEntryFilled
。
编辑
或者使用setClickable(false)
或android:clickable="false"
代替setEnabled(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)
重新激活您的开关
【讨论】:
不,onCheckedChanged()
仅在启用开关时调用,在这种情况下不是。
当它被禁用时,setEnabled(false)
,这些监听器将不起作用,试试我的其他建议。
我知道如果需要可以在 onCheckChanged 中取消选中它的选项,但我的问题是我是否可以专门检测对禁用项目的点击。如果不可能,我可能需要求助于其他方法,但我确信有办法找出用户是否点击了禁用的开关。
disabled 将禁用所有事件监听器,但是...试试我的新建议【参考方案5】:
尝试在您的交换机上设置setFocusable(false)
和setEnabled(true)
。这样,当开关仍被“禁用”时,点击事件将被触发。取自this answer。
【讨论】:
【参考方案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
【讨论】:
如果开关被禁用,OnClickListerns 不起作用,这就是我的问题,如何查看禁用的开关是否被点击? 不要禁用开关,让它启用并应用此代码。 不,重点是保持禁用它并找到解决方法【参考方案7】:让ParentView
拦截ClickEvent
s或TouchEvent
s,当它检测到接收View
是否被禁用时,做你必须做的事情。
编辑
“禁用时不起作用?”
试试这些代码,我使用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_
android:layout_
android:layout_marginTop="70dp"
android:background="#273746">
<FrameLayout
android:layout_
android:id="@+id/ass"
android:background="@drawable/abc_popup_background_mtrl_mult"
android:layout_>
</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 数组中解救出来
【讨论】:
如果禁用另一种向我询问 sn-p 的方式不起作用?如果是的话,你可以问@RuchirBaronia 检查我的编辑兄弟,如果它有帮助请告诉我@RuchirBaronia【参考方案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() 被调用时,如果开关值打开,您可以弹出对话框,当用户单击确定时,您默认将开关恢复为关闭。
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_
android:layout_
>
<!--Root layout to toggle button with same height and width
of toggle button-->
<LinearLayout
android:layout_
android:id="@+id/linear"
android:layout_>
<ToggleButton
style="?android:attr/buttonStyleSmall"
android:layout_
android:layout_
android:id="@+id/button"
/>
</LinearLayout>
</RelativeLayout>
当你禁用按钮时,将按钮设为不可聚焦和可点击。然后操作系统会将触摸功能移交给rootlayout。在root layout click listner中我们可以编写按钮未启用时的点击逻辑
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);
【讨论】:
以上是关于有一个禁用的onClick?的主要内容,如果未能解决你的问题,请参考以下文章