经过大量实验,这里有两个可行的解决方案!我在我的两台设备上对它们进行了测试——Nexus 7 运行 4.2.1,Kyocera C5170 运行 4.0.4。我的首选是解决方案 2。
解决方案 1
首先,诀窍是在 EditText 有机会完成它的工作之前确定 onTouch 而不是 onClick 中的光标位置 - 特别是在它弹出键盘之前。
一个额外的评论:一定要在你的清单中为弹出窗口设置 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) // or whatever condition
showPopup (this); // or whatever you want to do
}
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 ()
{
// Do this asynch so that EditText can finish setting the selectino.
@Override
public void run()
{
int selStart = getSelectionStart();
int selEnd = getSelectionEnd();
// If selStart is different than selEnd, user has highlighed an area of
// text; I chose to ignore the click when this happens.
if (selStart == selEnd)
if (selStart >= 0 && selStart < 10) // or whatever range you want
showPopup (this);
}
});
break;
}
}
return false;
}
private void showPopup (final EditText text)
{
Intent intent = new Intent (getContext(), Popup.class);
((Activity)getContext()).startActivity (intent);
}
}