经过许多实验,这里有两个可行的解决方案!我在我的两个设备上测试了它们——Nexus 7运行4.2.1,Kyocera C5170运行4.0.4。我更喜欢解决方案2。
解决方案1
对于第一个解决方案,技巧是在onTouch中确定光标位置,而不是在EditText执行其工作之前——特别是在弹出键盘之前。
另外一点说明:确保在您的清单中为弹出窗口设置android:windowSoftInputMode="stateHidden",否则您将会得到键盘和弹出窗口。
以下是整个代码:
public class ClickText extends EditText implements OnTouchListener
{
public ClickText (Context context, AttributeSet attrs)
{
super (context, attrs);
setOnTouchListener (this);
}
@Override
public boolean onTouch (View v, MotionEvent event)
{
if (event.getActionMasked() == MotionEvent.ACTION_DOWN)
{
int line = getLayout().getLineForVertical ((int)event.getY());
int onTouchCursorPos = getLayout().getOffsetForHorizontal (line, event.getX());
if (onTouchCursorPos < 10)
showPopup (this);
}
return false;
}
private void showPopup (final EditText text)
{
Intent intent = new Intent (getContext(), Popup.class);
((Activity)getContext()).startActivity (intent);
}
}
解决方案2
这个方案实际上更简单,我认为也更好——副作用更少。
这里的诀窍是让EditText完成其所有点击处理,然后异步地覆盖它。大意是:等待触摸“松开”——MotionEvent.ACTION_UP——然后不是立即执行您的操作,而是将一个Runnable发布到事件队列中,在那里执行您的操作。
整个代码:
public class ClickText extends EditText implements OnTouchListener
{
public ClickText (Context context, AttributeSet attrs)
{
super (context, attrs);
setOnTouchListener (this);
}
@Override
public boolean onTouch (View v, MotionEvent event)
{
switch (event.getActionMasked())
{
case MotionEvent.ACTION_UP:
{
post (new Runnable ()
{
@Override
public void run()
{
int selStart = getSelectionStart();
int selEnd = getSelectionEnd();
if (selStart == selEnd)
if (selStart >= 0 && selStart < 10)
showPopup (this);
}
});
break;
}
}
return false;
}
private void showPopup (final EditText text)
{
Intent intent = new Intent (getContext(), Popup.class);
((Activity)getContext()).startActivity (intent);
}
}