次のXMLを使用して、EditText
ウィジェットのテキストの右側に画像を追加しました。
<EditText
Android:id="@+id/txtsearch"
...
Android:layout_gravity="center_vertical"
Android:background="@layout/shape"
Android:hint="Enter place,city,state"
Android:drawableRight="@drawable/cross" />
ただし、埋め込み画像がクリックされたときにEditText
をクリアしたいと思います。これどうやってするの?
実際、クラスを拡張する必要はありません。 drawableRightのEditText editCommentがあるとします
editComment.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
final int DRAWABLE_TOP = 1;
final int DRAWABLE_RIGHT = 2;
final int DRAWABLE_BOTTOM = 3;
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() >= (editComment.getRight() - editComment.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
// your action here
return true;
}
}
return false;
}
});
getRawX()
は、親に対する相対ではなく、画面上の実際のタッチ位置を取得するためです。
左側をクリックするには
if(event.getRawX() <= (editComment.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width()))
この議論に貢献してくれたすべての人に感謝します。したがって、クラスを拡張する不便さに対処したくない場合は、次のことを行うことができます(適切なドロアブルのみに実装されます)
this.keyword = (AutoCompleteTextView) findViewById(R.id.search);
this.keyword.setOnTouchListener(new RightDrawableOnTouchListener(keyword) {
@Override
public boolean onDrawableTouch(final MotionEvent event) {
return onClickSearch(keyword,event);
}
});
private boolean onClickSearch(final View view, MotionEvent event) {
// do something
event.setAction(MotionEvent.ACTION_CANCEL);
return false;
}
そして、@ Markの答えに基づいたベアボーンリスナーの実装があります
public abstract class RightDrawableOnTouchListener implements OnTouchListener {
Drawable drawable;
private int fuzz = 10;
/**
* @param keyword
*/
public RightDrawableOnTouchListener(TextView view) {
super();
final Drawable[] drawables = view.getCompoundDrawables();
if (drawables != null && drawables.length == 4)
this.drawable = drawables[2];
}
/*
* (non-Javadoc)
*
* @see Android.view.View.OnTouchListener#onTouch(Android.view.View, Android.view.MotionEvent)
*/
@Override
public boolean onTouch(final View v, final MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN && drawable != null) {
final int x = (int) event.getX();
final int y = (int) event.getY();
final Rect bounds = drawable.getBounds();
if (x >= (v.getRight() - bounds.width() - fuzz) && x <= (v.getRight() - v.getPaddingRight() + fuzz)
&& y >= (v.getPaddingTop() - fuzz) && y <= (v.getHeight() - v.getPaddingBottom()) + fuzz) {
return onDrawableTouch(event);
}
}
return false;
}
public abstract boolean onDrawableTouch(final MotionEvent event);
}
以下を考慮してください。これは最もエレガントなソリューションではありませんが、動作します。テストしました。
カスタマイズされたEditText
クラスCustomEditText.Java
を作成します。
import Android.content.Context;
import Android.graphics.Rect;
import Android.graphics.drawable.Drawable;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.widget.EditText;
public class CustomEditText extends EditText
{
private Drawable dRight;
private Rect rBounds;
public CustomEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomEditText(Context context) {
super(context);
}
@Override
public void setCompoundDrawables(Drawable left, Drawable top,
Drawable right, Drawable bottom)
{
if(right !=null)
{
dRight = right;
}
super.setCompoundDrawables(left, top, right, bottom);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_UP && dRight!=null)
{
rBounds = dRight.getBounds();
final int x = (int)event.getX();
final int y = (int)event.getY();
//System.out.println("x:/y: "+x+"/"+y);
//System.out.println("bounds: "+bounds.left+"/"+bounds.right+"/"+bounds.top+"/"+bounds.bottom);
//check to make sure the touch event was within the bounds of the drawable
if(x>=(this.getRight()-rBounds.width()) && x<=(this.getRight()-this.getPaddingRight())
&& y>=this.getPaddingTop() && y<=(this.getHeight()-this.getPaddingBottom()))
{
//System.out.println("touch");
this.setText("");
event.setAction(MotionEvent.ACTION_CANCEL);//use this to prevent the keyboard from coming up
}
}
return super.onTouchEvent(event);
}
@Override
protected void finalize() throws Throwable
{
dRight = null;
rBounds = null;
super.finalize();
}
}
レイアウトXMLを次のように変更します(com.example
は実際のプロジェクトパッケージ名です):
<com.example.CustomEditText
Android:id="@+id/txtsearch"
…
Android:layout_gravity="center_vertical"
Android:background="@layout/shape"
Android:hint="Enter place,city,state"
Android:drawableRight="@drawable/cross"
/>
最後に、これにアクティビティ(または同様のもの)をアクティビティに追加します。
…
CustomEditText et = (CustomEditText) this.findViewById(R.id.txtsearch);
…
入れ子になったドロウアブルのタッチ境界の計算は少しおかしいかもしれませんが、アイデアは得られます。
これがお役に立てば幸いです。
OnTouchListenerを実装する便利な抽象クラスDrawableClickListenerを作成しました。
DrawableClickListenerクラスに加えて、DrawableClickListenerクラスを拡張し、正しい象限の描画可能領域のクリックを処理する4つの追加の抽象クラスも作成しました。
考慮する点
考慮すべきことの1つは、この方法で画像をサイズ変更しないことです。したがって、イメージはres/drawableフォルダーに入れる前に正しくスケーリングする必要があります。
ImageViewおよびTextViewを含むLinearLayoutを定義すると、表示される画像のサイズを操作するのがはるかに簡単になります。
activity_my.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent" >
<TextView
Android:id="@+id/myTextView"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="replace this with a variable"
Android:textSize="30sp"
Android:drawableLeft="@drawable/my_left_image"
Android:drawableRight="@drawable/my_right_image"
Android:drawablePadding="9dp" />
</RelativeLayout>
MyActivity.Java
package com.company.project.core;
import Android.app.Activity;
import Android.os.Bundle;
import Android.widget.TextView;
public class MyActivity extends Activity
{
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_my );
final TextView myTextView = (TextView) this.findViewById( R.id.myTextView );
myTextView.setOnTouchListener( new DrawableClickListener.LeftDrawableClickListener(myTextView)
{
@Override
public boolean onDrawableClick()
{
// TODO : insert code to perform on clicking of the LEFT drawable image...
return true;
}
} );
myTextView.setOnTouchListener( new DrawableClickListener.RightDrawableClickListener(myTextView)
{
@Override
public boolean onDrawableClick()
{
// TODO : insert code to perform on clicking of the RIGHT drawable image...
return true;
}
} );
}
}
DrawableClickListener.Java
package com.company.project.core;
import Android.graphics.Rect;
import Android.graphics.drawable.Drawable;
import Android.view.MotionEvent;
import Android.view.View;
import Android.view.View.OnTouchListener;
import Android.widget.TextView;
/**
* This class can be used to define a listener for a compound drawable.
*
* @author Matthew Weiler
* */
public abstract class DrawableClickListener implements OnTouchListener
{
/* PUBLIC CONSTANTS */
/**
* This represents the left drawable.
* */
public static final int DRAWABLE_INDEX_LEFT = 0;
/**
* This represents the top drawable.
* */
public static final int DRAWABLE_INDEX_TOP = 1;
/**
* This represents the right drawable.
* */
public static final int DRAWABLE_INDEX_RIGHT = 2;
/**
* This represents the bottom drawable.
* */
public static final int DRAWABLE_INDEX_BOTTOM = 3;
/**
* This stores the default value to be used for the
* {@link DrawableClickListener#fuzz}.
* */
public static final int DEFAULT_FUZZ = 10;
/* PRIVATE VARIABLES */
/**
* This stores the number of pixels of "fuzz" that should be
* included to account for the size of a finger.
* */
private final int fuzz;
/**
* This will store a reference to the {@link Drawable}.
* */
private Drawable drawable = null;
/* CONSTRUCTORS */
/**
* This will create a new instance of a {@link DrawableClickListener}
* object.
*
* @param view
* The {@link TextView} that this {@link DrawableClickListener}
* is associated with.
* @param drawableIndex
* The index of the drawable that this
* {@link DrawableClickListener} pertains to.
* <br />
* <i>use one of the values:
* <b>DrawableOnTouchListener.DRAWABLE_INDEX_*</b></i>
*/
public DrawableClickListener( final TextView view, final int drawableIndex )
{
this( view, drawableIndex, DrawableClickListener.DEFAULT_FUZZ );
}
/**
* This will create a new instance of a {@link DrawableClickListener}
* object.
*
* @param view
* The {@link TextView} that this {@link DrawableClickListener}
* is associated with.
* @param drawableIndex
* The index of the drawable that this
* {@link DrawableClickListener} pertains to.
* <br />
* <i>use one of the values:
* <b>DrawableOnTouchListener.DRAWABLE_INDEX_*</b></i>
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public DrawableClickListener( final TextView view, final int drawableIndex, final int fuzz )
{
super();
this.fuzz = fuzz;
final Drawable[] drawables = view.getCompoundDrawables();
if ( drawables != null && drawables.length == 4 )
{
this.drawable = drawables[drawableIndex];
}
}
/* OVERRIDDEN PUBLIC METHODS */
@Override
public boolean onTouch( final View v, final MotionEvent event )
{
if ( event.getAction() == MotionEvent.ACTION_DOWN && drawable != null )
{
final int x = (int) event.getX();
final int y = (int) event.getY();
final Rect bounds = drawable.getBounds();
if ( this.isClickOnDrawable( x, y, v, bounds, this.fuzz ) )
{
return this.onDrawableClick();
}
}
return false;
}
/* PUBLIC METHODS */
/**
*
* */
public abstract boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz );
/**
* This method will be fired when the drawable is touched/clicked.
*
* @return
* <code>true</code> if the listener has consumed the event;
* <code>false</code> otherwise.
* */
public abstract boolean onDrawableClick();
/* PUBLIC CLASSES */
/**
* This class can be used to define a listener for a <b>LEFT</b> compound
* drawable.
* */
public static abstract class LeftDrawableClickListener extends DrawableClickListener
{
/* CONSTRUCTORS */
/**
* This will create a new instance of a
* {@link LeftDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link LeftDrawableClickListener} is associated with.
*/
public LeftDrawableClickListener( final TextView view )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_LEFT );
}
/**
* This will create a new instance of a
* {@link LeftDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link LeftDrawableClickListener} is associated with.
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public LeftDrawableClickListener( final TextView view, final int fuzz )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_LEFT, fuzz );
}
/* PUBLIC METHODS */
public boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz )
{
if ( x >= ( view.getPaddingLeft() - fuzz ) )
{
if ( x <= ( view.getPaddingLeft() + drawableBounds.width() + fuzz ) )
{
if ( y >= ( view.getPaddingTop() - fuzz ) )
{
if ( y <= ( view.getHeight() - view.getPaddingBottom() + fuzz ) )
{
return true;
}
}
}
}
return false;
}
}
/**
* This class can be used to define a listener for a <b>TOP</b> compound
* drawable.
* */
public static abstract class TopDrawableClickListener extends DrawableClickListener
{
/* CONSTRUCTORS */
/**
* This will create a new instance of a {@link TopDrawableClickListener}
* object.
*
* @param view
* The {@link TextView} that this
* {@link TopDrawableClickListener} is associated with.
*/
public TopDrawableClickListener( final TextView view )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_TOP );
}
/**
* This will create a new instance of a {@link TopDrawableClickListener}
* object.
*
* @param view
* The {@link TextView} that this
* {@link TopDrawableClickListener} is associated with.
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public TopDrawableClickListener( final TextView view, final int fuzz )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_TOP, fuzz );
}
/* PUBLIC METHODS */
public boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz )
{
if ( x >= ( view.getPaddingLeft() - fuzz ) )
{
if ( x <= ( view.getWidth() - view.getPaddingRight() + fuzz ) )
{
if ( y >= ( view.getPaddingTop() - fuzz ) )
{
if ( y <= ( view.getPaddingTop() + drawableBounds.height() + fuzz ) )
{
return true;
}
}
}
}
return false;
}
}
/**
* This class can be used to define a listener for a <b>RIGHT</b> compound
* drawable.
* */
public static abstract class RightDrawableClickListener extends DrawableClickListener
{
/* CONSTRUCTORS */
/**
* This will create a new instance of a
* {@link RightDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link RightDrawableClickListener} is associated with.
*/
public RightDrawableClickListener( final TextView view )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_RIGHT );
}
/**
* This will create a new instance of a
* {@link RightDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link RightDrawableClickListener} is associated with.
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public RightDrawableClickListener( final TextView view, final int fuzz )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_RIGHT, fuzz );
}
/* PUBLIC METHODS */
public boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz )
{
if ( x >= ( view.getWidth() - view.getPaddingRight() - drawableBounds.width() - fuzz ) )
{
if ( x <= ( view.getWidth() - view.getPaddingRight() + fuzz ) )
{
if ( y >= ( view.getPaddingTop() - fuzz ) )
{
if ( y <= ( view.getHeight() - view.getPaddingBottom() + fuzz ) )
{
return true;
}
}
}
}
return false;
}
}
/**
* This class can be used to define a listener for a <b>BOTTOM</b> compound
* drawable.
* */
public static abstract class BottomDrawableClickListener extends DrawableClickListener
{
/* CONSTRUCTORS */
/**
* This will create a new instance of a
* {@link BottomDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link BottomDrawableClickListener} is associated with.
*/
public BottomDrawableClickListener( final TextView view )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_BOTTOM );
}
/**
* This will create a new instance of a
* {@link BottomDrawableClickListener} object.
*
* @param view
* The {@link TextView} that this
* {@link BottomDrawableClickListener} is associated with.
* @param fuzzOverride
* The number of pixels of "fuzz" that should be
* included to account for the size of a finger.
*/
public BottomDrawableClickListener( final TextView view, final int fuzz )
{
super( view, DrawableClickListener.DRAWABLE_INDEX_BOTTOM, fuzz );
}
/* PUBLIC METHODS */
public boolean isClickOnDrawable( final int x, final int y, final View view, final Rect drawableBounds, final int fuzz )
{
if ( x >= ( view.getPaddingLeft() - fuzz ) )
{
if ( x <= ( view.getWidth() - view.getPaddingRight() + fuzz ) )
{
if ( y >= ( view.getHeight() - view.getPaddingBottom() - drawableBounds.height() - fuzz ) )
{
if ( y <= ( view.getHeight() - view.getPaddingBottom() + fuzz ) )
{
return true;
}
}
}
}
return false;
}
}
}
とても簡単です。 EditText 'txtsearch'の左側にドロウアブルがあるとしましょう。以下はトリックを行います。
EditText txtsearch = (EditText) findViewById(R.id.txtsearch);
txtsearch.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() <= txtsearch.getTotalPaddingLeft()) {
// your action for drawable click event
return true;
}
}
return false;
}
});
正しいドローアブルが必要な場合は、ifステートメントを次のように変更します。
if(event.getRawX() >= txtsearch.getRight() - txtsearch.getTotalPaddingRight())
同様に、すべての複合ドロウアブルに対しても実行できます。
txtsearch.getTotalPaddingTop()
txtsearch.getTotalPaddingBottom()
このメソッド呼び出しは、ドロアブルを含むその側のすべてのパディングを返します。これはTextView、Buttonなどにも使用できます。
Android開発者サイトからの参照用に here をクリックします。
最後のコントリビューションがcontains(x,y)
を使用しても、getBounds()
の結果には直接作用しません(偶然、「左」のドロアブルを使用する場合を除く)。 getBounds
メソッドは、Originを0,0に正規化したドロアブルアイテムのRect
定義ポイントのみを提供します。したがって、実際に元の投稿の数学を実行して、コンテキスト内のドロアブルの領域にクリックがあるかどうかを確認する必要があります含まれるEditTextの次元の、ただし上、右、左などに変更します。代わりに、実際にはRect
コンテナ内の位置に相対的な座標を持つEditText
を記述し、contains()
を使用できます。 。
両方を組み合わせることで、非常に完全なソリューションが得られます。その結果を使用してACTION_CANCEL
を設定するかどうかでクリックイベントを渡すかどうかをAPIユーザーが決定できるインスタンス属性consumesEvent
のみを追加しました。
また、bounds
およびactionX
、actionY
の値が、スタック上の単なるローカルではなく、インスタンス属性である理由がわかりません。
ここに、上記に基づいた実装の一部をまとめました。イベントを適切に消費するには、falseを返す必要があるという問題を修正します。 「ファズ」要素を追加します。 EditText
フィールドの音声コントロールアイコンの使用例では、クリックするのが難しいことがわかりました。そのため、ファズは、ドロアブルをクリックすると見なされる有効な境界を増やします。私にとって15
はうまく機能しました。 drawableRight
だけが必要だったので、スペースを節約するために数学を他の数学に差し込むことはしませんでしたが、アイデアはわかります。
package com.example.Android;
import Android.content.Context;
import Android.graphics.drawable.Drawable;
import Android.util.AttributeSet;
import Android.util.Log;
import Android.view.MotionEvent;
import Android.widget.EditText;
import Android.graphics.Rect;
import com.example.Android.DrawableClickListener;
public class ClickableButtonEditText extends EditText {
public static final String LOG_TAG = "ClickableButtonEditText";
private Drawable drawableRight;
private Drawable drawableLeft;
private Drawable drawableTop;
private Drawable drawableBottom;
private boolean consumeEvent = false;
private int fuzz = 0;
private DrawableClickListener clickListener;
public ClickableButtonEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ClickableButtonEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ClickableButtonEditText(Context context) {
super(context);
}
public void consumeEvent() {
this.setConsumeEvent(true);
}
public void setConsumeEvent(boolean b) {
this.consumeEvent = b;
}
public void setFuzz(int z) {
this.fuzz = z;
}
public int getFuzz() {
return fuzz;
}
@Override
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
if (right != null) {
drawableRight = right;
}
if (left != null) {
drawableLeft = left;
}
super.setCompoundDrawables(left, top, right, bottom);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x, y;
Rect bounds;
x = (int) event.getX();
y = (int) event.getY();
// this works for left since container shares 0,0 Origin with bounds
if (drawableLeft != null) {
bounds = drawableLeft.getBounds();
if (bounds.contains(x - fuzz, y - fuzz)) {
clickListener.onClick(DrawableClickListener.DrawablePosition.LEFT);
if (consumeEvent) {
event.setAction(MotionEvent.ACTION_CANCEL);
return false;
}
}
} else if (drawableRight != null) {
bounds = drawableRight.getBounds();
if (x >= (this.getRight() - bounds.width() - fuzz) && x <= (this.getRight() - this.getPaddingRight() + fuzz)
&& y >= (this.getPaddingTop() - fuzz) && y <= (this.getHeight() - this.getPaddingBottom()) + fuzz) {
clickListener.onClick(DrawableClickListener.DrawablePosition.RIGHT);
if (consumeEvent) {
event.setAction(MotionEvent.ACTION_CANCEL);
return false;
}
}
} else if (drawableTop != null) {
// not impl reader exercise :)
} else if (drawableBottom != null) {
// not impl reader exercise :)
}
}
return super.onTouchEvent(event);
}
@Override
protected void finalize() throws Throwable {
drawableRight = null;
drawableBottom = null;
drawableLeft = null;
drawableTop = null;
super.finalize();
}
public void setDrawableClickListener(DrawableClickListener listener) {
this.clickListener = listener;
}
}
私たちはいくつかのトリックを使用する方がはるかに簡単だと思います:)
完了
RyanMのアイデアを拡張して、より柔軟なバージョンを作成しました。これは、すべての描画可能タイプ(上、下、左、右)をサポートします。以下のコードはTextViewを拡張しますが、EditTextに適応させるのは、「extends TextView」を「extends EditText」と交換する場合にすぎません。 XMLからのウィジェットのインスタンス化は、RyanMの例と同じで、ウィジェット名を禁止します。
import Android.content.Context;
import Android.graphics.drawable.Drawable;
import Android.util.AttributeSet;
import Android.util.Log;
import Android.view.MotionEvent;
import Android.widget.TextView;
import com.example.DrawableClickListener.DrawablePosition;
public class ButtonTextView extends TextView {
private Drawable drawableRight;
private Drawable drawableLeft;
private Drawable drawableTop;
private Drawable drawableBottom;
private int actionX, actionY;
private DrawableClickListener clickListener;
public ButtonTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ButtonTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ButtonTextView(Context context) {
super(context);
}
@Override
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
if (right != null) {
drawableRight = right;
}
if (left != null) {
drawableLeft = left;
}
if (top != null) {
drawableTop = top;
}
if (bottom != null) {
drawableBottom = bottom;
}
super.setCompoundDrawables(left, top, right, bottom);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
actionX = (int) event.getX();
actionY = (int) event.getY();
if (drawableBottom != null && drawableBottom.getBounds().contains(actionX, actionY)) {
clickListener.onClick(DrawablePosition.BOTTOM);
return super.onTouchEvent(event);
}
if (drawableTop != null && drawableTop.getBounds().contains(actionX, actionY)) {
clickListener.onClick(DrawablePosition.TOP);
return super.onTouchEvent(event);
}
if (drawableLeft != null && drawableLeft.getBounds().contains(actionX, actionY)) {
clickListener.onClick(DrawablePosition.LEFT);
return super.onTouchEvent(event);
}
if (drawableRight != null && drawableRight.getBounds().contains(actionX, actionY)) {
clickListener.onClick(DrawablePosition.RIGHT);
return super.onTouchEvent(event);
}
}
return super.onTouchEvent(event);
}
@Override
protected void finalize() throws Throwable {
drawableRight = null;
drawableBottom = null;
drawableLeft = null;
drawableTop = null;
super.finalize();
}
public void setDrawableClickListener(DrawableClickListener listener) {
this.clickListener = listener;
}}
DrawableClickListenerは次のように簡単です。
public interface DrawableClickListener {
public static enum DrawablePosition { TOP, BOTTOM, LEFT, RIGHT };
public void onClick(DrawablePosition target); }
そして、実際の実装:
class example implements DrawableClickListener {
public void onClick(DrawablePosition target) {
switch (target) {
case LEFT:
doSomethingA();
break;
case RIGHT:
doSomethingB();
break;
case BOTTOM:
doSomethingC();
break;
case TOP:
doSomethingD();
break;
default:
break;
}
}}
p.s .:リスナーを設定しない場合、TextViewをタッチするとNullPointerExceptionが発生します。コードにさらにパラノイアを追加することもできます。
私のために働いて、
mEditTextSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(s.length()>0){
mEditTextSearch.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(Android.R.drawable.ic_delete), null);
}else{
mEditTextSearch.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(R.drawable.abc_ic_search), null);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
mEditTextSearch.setOnTouchListener(new OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
if(mEditTextSearch.getCompoundDrawables()[2]!=null){
if(event.getX() >= (mEditTextSearch.getRight()- mEditTextSearch.getLeft() - mEditTextSearch.getCompoundDrawables()[2].getBounds().width())) {
mEditTextSearch.setText("");
}
}
}
return false;
}
});
私はこれがかなり古いことを知っていますが、最近似たようなことをしなければなりませんでした...これがどれほど難しいかを見た後、もっと簡単な解決策を思いつきました。
私の場合、ボタンでテキストをクリアする機能を持つEditTextが必要でした。 SearchViewのように見せたかったのですが、いくつかの理由から、このクラスを使用したくありませんでした。以下の例は、これをどのように達成したかを示しています。フォーカスの変更とは関係ありませんが、原則は同じであり、実際に動作するコードを投稿する方が、意図したとおりに動作しない可能性のある例をまとめるよりも有益だと考えました。
これが私のレイアウトです:clearable_edit_text.xml
<merge
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<EditText
Android:id="@+id/edit_text_field"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"/>
<!-- NOTE: Visibility cannot be set to "gone" or the padding won't get set properly in code -->
<ImageButton
Android:id="@+id/edit_text_clear"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="right|center_vertical"
Android:background="@drawable/ic_cancel_x"
Android:visibility="invisible"/>
</merge>
そして、そのレイアウトを拡張するクラスは次のとおりです。ClearableEditText.Java
public class ClearableEditText extends FrameLayout {
private boolean mPaddingSet = false;
/**
* Creates a new instance of this class.
* @param context The context used to create the instance
*/
public ClearableEditText (final Context context) {
this(context, null, 0);
}
/**
* Creates a new instance of this class.
* @param context The context used to create the instance
* @param attrs The attribute set used to customize this instance
*/
public ClearableEditText (final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* Creates a new instance of this class.
* @param context The context used to create the instance
* @param attrs The attribute set used to customize this instance
* @param defStyle The default style to be applied to this instance
*/
public ClearableEditText (final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
final LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.clearable_edit_text, this, true);
}
@Override
protected void onFinishInflate () {
super.onFinishInflate();
final EditText editField = (EditText) findViewById(R.id.edit_text_field);
final ImageButton clearButton = (ImageButton) findViewById(R.id.edit_text_clear);
//Set text listener so we can show/hide the close button based on whether or not it has text
editField.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged (final CharSequence charSequence, final int i, final int i2, final int i3) {
//Do nothing here
}
@Override
public void onTextChanged (final CharSequence charSequence, final int i, final int i2, final int i3) {
//Do nothing here
}
@Override
public void afterTextChanged (final Editable editable) {
clearButton.setVisibility(editable.length() > 0 ? View.VISIBLE : View.INVISIBLE);
}
});
//Set the click listener for the button to clear the text. The act of clearing the text will hide this button because of the
//text listener
clearButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick (final View view) {
editField.setText("");
}
});
}
@Override
protected void onLayout (final boolean changed, final int left, final int top, final int right, final int bottom) {
super.onLayout(changed, left, top, right, bottom);
//Set padding here in the code so the text doesn't run into the close button. This could be done in the XML layout, but then if
//the size of the image changes then we constantly need to Tweak the padding when the image changes. This way it happens automatically
if (!mPaddingSet) {
final EditText editField = (EditText) findViewById(R.id.edit_text_field);
final ImageButton clearButton = (ImageButton) findViewById(R.id.edit_text_clear);
editField.setPadding(editField.getPaddingLeft(), editField.getPaddingTop(), clearButton.getWidth(), editField.getPaddingBottom());
mPaddingSet = true;
}
}
}
この回答を質問と一致させるために、次の手順を実行する必要があります。
次のコードをコピーして貼り付けるだけで、うまくいきます。
editMsg.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
final int DRAWABLE_TOP = 1;
final int DRAWABLE_RIGHT = 2;
final int DRAWABLE_BOTTOM = 3;
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() >= (editMsg.getRight() - editMsg.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
// your action here
Toast.makeText(ChatActivity.this, "Message Sent", Toast.LENGTH_SHORT).show();
return true;
}
}
return false;
}
});
ドロアブルが左側にある場合、これはあなたを助けます。 (RTLレイアウトを使用する場合)
editComment.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
final int DRAWABLE_TOP = 1;
final int DRAWABLE_RIGHT = 2;
final int DRAWABLE_BOTTOM = 3;
if(event.getAction() == MotionEvent.ACTION_UP) {
if (event.getRawX() <= (searchbox.getLeft() + searchbox.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width())) {
// your action here
return true;
}
}
return false;
}
});
複合ドロウアブルはクリック可能であるとは想定されていません。水平のLinearLayoutで個別のビューを使用し、それらにクリックハンドラーを使用すると、よりクリーンになります。
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginTop="15dp"
Android:background="@color/white"
Android:layout_marginLeft="20dp"
Android:layout_marginStart="20dp"
Android:layout_marginRight="20dp"
Android:layout_marginEnd="20dp"
Android:layout_gravity="center_horizontal"
Android:orientation="horizontal"
Android:translationZ="4dp">
<ImageView
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:background="@color/white"
Android:minWidth="40dp"
Android:scaleType="center"
app:srcCompat="@drawable/ic_search_map"/>
<Android.support.design.widget.TextInputEditText
Android:id="@+id/search_edit"
style="@style/EditText.Registration.Map"
Android:layout_width="0dp"
Android:layout_weight="1"
Android:layout_height="wrap_content"
Android:hint="@string/hint_location_search"
Android:imeOptions="actionSearch"
Android:inputType="textPostalAddress"
Android:maxLines="1"
Android:minHeight="40dp" />
<ImageView
Android:id="@+id/location_gps_refresh"
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:background="@color/white"
Android:minWidth="40dp"
Android:scaleType="center"
app:srcCompat="@drawable/selector_ic_gps"/>
</LinearLayout>
巨大なクリック処理を実装したくない人のために。 RelativeLayout
でも同じことができます。それにより、ドロウアブルの位置を自由に扱うことさえできます。
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<Android.support.design.widget.TextInputLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<Android.support.design.widget.TextInputEditText
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
/>
</Android.support.design.widget.TextInputLayout>
<ImageView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_alignParentEnd="true"
Android:layout_centerInParent="true"
Android:src="@drawable/ic_undo"/>
</RelativeLayout>
ImageView
の位置は、drawableEnd
を使用する場合と同じになります-さらに、すべてのタッチリスナーの処理は必要ありません。 ImageView
のクリックリスナーだけで準備完了です。
これは私のために働く:)これはあなたにも役立つかもしれません
edit_account_name.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (event.getRawX() >= (edit_account_name.getRight())) {
//clicked
return true;
}
}
return false;
}
});
編集テキストの右側に画像ボタンを配置し、編集テキストと重なる負のレイアウトマージンを与える方が良いでしょう。画像ボタンにリスナーを設定し、操作を実行します。
左の描画可能なクリックリスナーの場合
txt.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
if (event.getAction() == MotionEvent.ACTION_UP) {
if (event.getRawX() <= (txt
.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width() +
txt.getPaddingLeft() +
txt.getLeft())) {
//TODO do code here
}
return true;
}
}
return false;
}
});
描画可能な右、左、上、下のクリックのコードの下に続く:
edittextview_confirmpassword.setOnTouchListener(new View.OnTouchListener() {
@Override public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
final int DRAWABLE_TOP = 1;
final int DRAWABLE_RIGHT = 2;
final int DRAWABLE_BOTTOM = 3;
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() >= (edittextview_confirmpassword.getRight() - edittextview_confirmpassword.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
// your action here edittextview_confirmpassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
return true;
}
}else{
edittextview_confirmpassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
}
return false;
}
});
}
それはすべて素晴らしいですが、なぜそれを本当にシンプルにしないのですか?
私もそんなに昔に直面していません...そしてAndroid touchlistinerはうまく機能しますが、使用法に制限があります。
<LinearLayout
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:id="@+id/zero_row">
<LinearLayout
Android:orientation="horizontal"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<LinearLayout
Android:orientation="horizontal"
Android:layout_width="wrap_content"
Android:layout_height="match_parent">
<ProgressBar
Android:id="@+id/loadingProgressBar"
Android:layout_gravity="center"
Android:layout_width="28dp"
Android:layout_height="28dp" />
</LinearLayout>
<LinearLayout
Android:orientation="horizontal"
Android:layout_width="match_parent"
Android:background="@drawable/edittext_round_corners"
Android:layout_height="match_parent"
Android:layout_marginLeft="5dp">
<ImageView
Android:layout_width="28dp"
Android:layout_height="28dp"
app:srcCompat="@Android:drawable/ic_menu_search"
Android:id="@+id/imageView2"
Android:layout_weight="0.15"
Android:layout_gravity="center|right"
Android:onClick="OnDatabaseSearchEvent" />
<EditText
Android:minHeight="40dp"
Android:layout_marginLeft="10dp"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:background="@drawable/edittext_round_corners"
Android:inputType="textPersonName"
Android:hint="Search.."
Android:textColorHint="@color/AndroidWhite"
Android:textColor="@color/AndroidWhite"
Android:ems="10"
Android:id="@+id/e_d_search"
Android:textCursorDrawable="@color/AndroidWhite"
Android:layout_weight="1" />
<ImageView
Android:layout_width="28dp"
Android:layout_height="28dp"
app:srcCompat="@drawable/ic_oculi_remove2"
Android:id="@+id/imageView3"
Android:layout_gravity="center|left"
Android:layout_weight="0.15"
Android:onClick="onSearchEditTextCancel" />
</LinearLayout>
<!--Android:drawableLeft="@Android:drawable/ic_menu_search"-->
<!--Android:drawableRight="@drawable/ic_oculi_remove2"-->
</LinearLayout>
</LinearLayout>
これで、ImageClickリスナーまたはイベントを作成し、テキストで必要なことを実行できます。このedittext_round_corners.xmlファイル
<item Android:state_pressed="false" Android:state_focused="false">
<shape>
<gradient
Android:centerY="0.2"
Android:startColor="@color/colorAccent"
Android:centerColor="@color/colorAccent"
Android:endColor="@color/colorAccent"
Android:angle="270"
/>
<stroke
Android:width="0.7dp"
Android:color="@color/colorAccent" />
<corners
Android:radius="5dp" />
</shape>
</item>
<FrameLayout
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:padding="5dp" >
<EditText
Android:id="@+id/edt_status_text"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_marginBottom="10dp"
Android:background="@drawable/txt_box_blank"
Android:ems="10"
Android:hint="@string/statusnote"
Android:paddingLeft="5dp"
Android:paddingRight="10dp"
Android:textColor="@Android:color/black" />
<Button
Android:id="@+id/note_del"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="right"
Android:layout_marginRight="1dp"
Android:layout_marginTop="5dp"
Android:background="@Android:drawable/ic_delete" />
</FrameLayout>
@Override
public boolean onTouch(View v, MotionEvent event) {
Drawable drawableObj = getResources().getDrawable(R.drawable.search_btn);
int drawableWidth = drawableObj.getIntrinsicWidth();
int x = (int) event.getX();
int y = (int) event.getY();
if (event != null && event.getAction() == MotionEvent.ACTION_UP) {
if (x >= (searchPanel_search.getWidth() - drawableWidth - searchPanel_search.getPaddingRight())
&& x <= (searchPanel_search.getWidth() - searchPanel_search.getPaddingRight())
&& y >= searchPanel_search.getPaddingTop() && y <= (searchPanel_search.getHeight() - searchPanel_search.getPaddingBottom())) {
getSearchData();
}
else {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(searchPanel_search, InputMethodManager.SHOW_FORCED);
}
}
return super.onTouchEvent(event);
}
TextView複合描画可能クリックおよびタッチイベントを処理するための一般的なソリューションを共有します。
まず、タッチイベントハンドラが必要です。
/**
* Handles compound drawable touch events.
* Will intercept every event that happened inside (calculated) compound drawable bounds, extended by fuzz.
* @see TextView#getCompoundDrawables()
* @see TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)
*/
public abstract class CompoundDrawableTouchListener implements View.OnTouchListener {
private final String LOG_TAG = "CmpDrawableTouch";
private final int fuzz;
public static final int LEFT = 0;
public static final int TOP = 1;
public static final int RIGHT = 2;
public static final int BOTTOM = 3;
private static final int[] DRAWABLE_INDEXES = {LEFT, TOP, RIGHT, BOTTOM};
/**
* Default constructor
*/
public CompoundDrawableTouchListener() {
this(0);
}
/**
* Constructor with fuzz
* @param fuzz desired fuzz in px
*/
public CompoundDrawableTouchListener(int fuzz) {
this.fuzz = fuzz;
}
@Override
public boolean onTouch(View view, MotionEvent event) {
if (!(view instanceof TextView)) {
Log.e(LOG_TAG, "attached view is not instance of TextView");
return false;
}
TextView textView = (TextView) view;
Drawable[] drawables = textView.getCompoundDrawables();
int x = (int) event.getX();
int y = (int) event.getY();
for (int i : DRAWABLE_INDEXES) {
if (drawables[i] == null) continue;
Rect bounds = getRelativeBounds(i, drawables[i], textView);
Rect fuzzedBounds = addFuzz(bounds);
if (fuzzedBounds.contains(x, y)) {
MotionEvent relativeEvent = MotionEvent.obtain(
event.getDownTime(),
event.getEventTime(),
event.getAction(),
event.getX() - bounds.left,
event.getY() - bounds.top,
event.getMetaState());
return onDrawableTouch(view, i, bounds, relativeEvent);
}
}
return false;
}
/**
* Calculates compound drawable bounds relative to wrapping view
* @param index compound drawable index
* @param drawable the drawable
* @param view wrapping view
* @return {@link Rect} with relative bounds
*/
private Rect getRelativeBounds(int index, @NonNull Drawable drawable, View view) {
Rect drawableBounds = drawable.getBounds();
Rect bounds = new Rect();
switch (index) {
case LEFT:
bounds.offsetTo(view.getPaddingLeft(),
view.getHeight() / 2 - bounds.height() / 2);
break;
case TOP:
bounds.offsetTo(view.getWidth() / 2 - bounds.width() / 2,
view.getPaddingTop());
break;
case RIGHT:
bounds.offsetTo(view.getWidth() - view.getPaddingRight() - bounds.width(),
view.getHeight() / 2 - bounds.height() / 2);
break;
case BOTTOM:
bounds.offsetTo(view.getWidth() / 2 - bounds.width() / 2,
view.getHeight() - view.getPaddingBottom() - bounds.height());
break;
}
return bounds;
}
/**
* Expands {@link Rect} by given value in every direction relative to its center
* @param source given {@link Rect}
* @return result {@link Rect}
*/
private Rect addFuzz(Rect source) {
Rect result = new Rect();
result.left = source.left - fuzz;
result.right = source.right + fuzz;
result.top = source.top - fuzz;
result.bottom = source.bottom + fuzz;
return result;
}
/**
* Compound drawable touch-event handler
* @param v wrapping view
* @param drawableIndex index of compound drawable which recicved the event
* @param drawableBounds {@link Rect} with compound drawable bounds relative to wrapping view.
* Fuzz not included
* @param event event with coordinated relative to wrapping view - i.e. within {@code drawableBounds}.
* If using fuzz, may return negative coordinates.
*/
protected abstract boolean onDrawableTouch(View v, int drawableIndex, Rect drawableBounds, MotionEvent event);
}
これで、この方法で好きなTextViewの複合ドローアブルのタッチイベントを処理できます。
textView1.setOnTouchListener(new CompoundDrawableTouchListener() {
@Override
protected void onDrawableTouch(View v, int drawableIndex, Rect drawableBounds, MotionEvent event) {
switch(v.getId()) {
case R.id.textView1:
switch(drawableIndex) {
case CompoundDrawableTouchListener.RIGHT:
doStuff();
break;
}
break;
}
}
});
クリックのみに関心がありますか? MotionEventアクションでフィルタリングするだけです:
/**
* Handles compound drawable click events.
* @see TextView#getCompoundDrawables()
* @see TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)
* @see CompoundDrawableTouchListener
*/
public abstract class CompoundDrawableClickListener extends CompoundDrawableTouchListener {
/**
* Default constructor
*/
public CompoundDrawableClickListener() {
super();
}
/**
* Constructor with fuzz
* @param fuzz desired fuzz in px
*/
public CompoundDrawableClickListener(int fuzz) {
super(fuzz);
}
@Override
protected void onDrawableTouch(View v, int drawableIndex, Rect drawableBounds, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) onDrawableClick(v, drawableIndex);
return true;
}
/**
* Compound drawable touch-event handler
* @param v wrapping view
* @param drawableIndex index of compound drawable which recicved the event
*/
protected abstract void onDrawableClick(View v, int drawableIndex);
}
この場合も、TextViewの複合ドロウアブルのクリックを簡単に処理できます。
textView1.setOnTouchListener(new CompoundDrawableClickListener() {
@Override
protected void onDrawableClick(View v, int drawableIndex) {
switch(v.getId()) {
case R.id.textView1:
switch(drawableIndex) {
case CompoundDrawableTouchListener.RIGHT:
doStuff();
break;
}
break;
}
}
});
私がしたようにあなたがそれを好き願っています。ここと 関連するGist で何かが変更された場合は、最新の状態に保つようにします。
カスタムEditTextの代わりにシンプルなカスタムタッチリスナクラスを作成しました
public class MyTouchListener implements View.OnTouchListener {
private EditText editText;
public MyTouchListener(EditText editText) {
this.editText = editText;
setupDrawable(this.editText);
}
private void setupDrawable(final EditText editText) {
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(s.length()>0)
editText.setCompoundDrawablesWithIntrinsicBounds(0,0, R.drawable.clearicon,0);
else
editText.setCompoundDrawablesWithIntrinsicBounds(0,0, 0,0);
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
if(editText.getCompoundDrawables()[2]!=null){
if(event.getX() >= (editText.getRight()- editText.getLeft() - editText.getCompoundDrawables()[2].getBounds().width())) {
editText.setText("");
}
}
}
return false;
}
}
EditTextが空白の場合、ドロアブルはありません。 EditTextをクリアするために編集を開始すると、ドロアブルが表示されます。
タッチリスナーを設定するだけです
mEditText.setOnTouchListener(new MyTouchListener(mEditText));
私はこのようなことをしました
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<Android.support.design.widget.TextInputLayout
Android:id="@+id/til_text"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_alignParentTop="true"
Android:textColorHint="@color/colorSilver">
<Android.support.design.widget.TextInputEditText
Android:id="@+id/tiet_text"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:gravity="top|left"
Android:hint="@string/rep_hint"
Android:inputType="textMultiLine"
Android:maxLines="3"
Android:drawableEnd="@drawable/ic_attach_photo"
Android:drawablePadding="5dp"
Android:textColor="@color/colorPrimaryText"
Android:textColorHint="@color/colorSilver"
/>
</Android.support.design.widget.TextInputLayout>
<View
Android:id="@+id/right_button"
Android:layout_width="24dp"
Android:layout_height="24dp"
Android:layout_centerVertical="true"
Android:layout_alignParentEnd="true"
Android:layout_marginEnd="12dp"
Android:background="@color/clear" />
</RelativeLayout>
描画可能な左の方法を提案したいと思います!このコードを試してみました。
txtsearch.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
int start=txtsearch.getSelectionStart();
int end=txtsearch.getSelectionEnd();
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() <= (txtsearch.getLeft() + txtsearch.getCompoundDrawables()[DRAWABLE_LEFT].getBounds().width())) {
//Do your action here
return true;
}
}
return false;
}
});
}
いくつかのソリューションを見てきましたが、それらのいずれにも納得できませんでした。非常に複雑または単純すぎる(再利用不可)。
これは現時点で私のお気に入りのアプローチです:
mEditText.setOnTouchListener(
new OnEditTextRightDrawableTouchListener(mEditText) {
@Override
public void OnDrawableClick() {
// The right drawable was clicked. Your action goes here.
}
});
そして、これは再利用可能なタッチリスナーです。
import Android.graphics.drawable.Drawable;
import Android.support.annotation.NonNull;
import Android.view.MotionEvent;
import Android.view.View;
import Android.view.View.OnTouchListener;
import Android.widget.EditText;
public abstract class OnEditTextRightDrawableTouchListener implements OnTouchListener {
private final EditText mEditText;
public OnEditTextRightDrawableTouchListener(@NonNull final EditText editText) {
mEditText = editText;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
final int DRAWABLE_RIGHT_POSITION = 2;
final Drawable drawable = mEditText.getCompoundDrawables()[DRAWABLE_RIGHT_POSITION];
if (drawable != null) {
final float touchEventX = motionEvent.getX();
final int touchAreaRight = mEditText.getRight();
final int touchAreaLeft = touchAreaRight - drawable.getBounds().width();
if (touchEventX >= touchAreaLeft && touchEventX <= touchAreaRight) {
view.performClick();
OnDrawableClick();
}
return true;
}
}
return false;
}
public abstract void OnDrawableClick();
}
@aristo_sh応答をMono.Droid(Xamarin)に実装しました。これは、e.Event.Handledを取得する必要があるtrueまたはfalseを返すことができない委任匿名メソッドであるためです。また、クリック時にキーボードを非表示にします
editText.Touch += (sender, e) => {
e.Handled = false;
if (e.Event.Action == MotionEventActions.Up)
{
if (e.Event.RawX >= (bibEditText.Right - (bibEditText.GetCompoundDrawables()[2]).Bounds.Width()))
{
SearchRunner();
InputMethodManager manager = (InputMethodManager)GetSystemService(InputMethodService);
manager.HideSoftInputFromWindow(editText.WindowToken, 0);
e.Handled = true;
}
}
};
Kotlinは、各クラスを新しいメソッドで拡張できる素晴らしい言語です。 EditTextクラスの新しいメソッドを導入して、クリックを適切なドロアブルにキャッチします。
fun EditText.onRightDrawableClicked(onClicked: (view: EditText) -> Unit) {
this.setOnTouchListener { v, event ->
var hasConsumed = false
if (v is EditText) {
if (event.x >= v.width - v.totalPaddingRight) {
if (event.action == MotionEvent.ACTION_UP) {
onClicked(this)
}
hasConsumed = true
}
}
hasConsumed
}
}
ユーザーが右のドロアブルをクリックすると呼び出されるコールバック関数を引数として取ることがわかります。
val username = findViewById<EditText>(R.id.username_text)
username.onRightDrawableClicked {
it.text.clear()
}
スパナブルテキストビューバッファを使用することが解決策になる可能性があります。この短いチュートリアルとポイントチュートリアルをご覧ください。クリックイベントを行う方がはるかに簡単です。
https://Android-designing.blogspot.com/2017/01/spannable-textview-with-image-clickable.html?m=1
非常に多くの解決策がありましたが、2つのフィールドが連続していた場合、私にとってはうまくいきませんでした。これは、テキストを編集するためのクリアボタンを追加するためのドロップインソリューションであり、2つのフィールドまたは1つのフィールドが連続している状況で機能しました。コトリンで書かれた!
@SuppressLint("PrivateResource")
fun <T : EditText> T.withClear(): T {
addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(editable: Editable) {
setCompoundDrawablesWithIntrinsicBounds(0, 0,
if (editable.isNotEmpty()) abc_ic_clear_material else 0, 0)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
})
setOnTouchListener { _, event ->
if (event.action == ACTION_UP && event.x >= (right - this.compoundPaddingRight)) {
setText("")
return@setOnTouchListener true
}
false
}
return this
}
これが私の簡単な解決策です。ImageButton
をEditText
の上に置くだけです:
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<EditText Android:id="@+id/editTextName"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:imeOptions="actionSearch"
Android:inputType="text"/>
<ImageButton Android:id="@+id/imageViewSearch"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:src="@drawable/ic_action_search"
Android:layout_alignParentRight="true"
Android:layout_centerVertical="true"/>
</RelativeLayout>
対話の断片にも適した短いソリューションを適用します。
//The listener of a drawableEnd button for clear a TextInputEditText
textValue.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP) {
final TextView textView = (TextView)v;
if(event.getX() >= textView.getWidth() - textView.getCompoundPaddingEnd()) {
textView.setText(""); //Clear a view, example: EditText or TextView
return true;
}
}
return false;
}
});
上記のソリューションは機能しますが、副作用があります。次のような正しいドローアブルを備えたEditTextがある場合
ドロアブルでクリックするたびにPASTEボタンが表示されます。 EditText Android(アイコンEditText内)のDrawable権限についてonClickListenerで貼り付けを無効にする方法 を参照してください。