AndroidアプリにonClickイベントが指定されたボタンのように使用しているimageviewがありますが、ご想像のとおり、クリックしたときにimageviewにクリック可能な効果が与えられていません。どうすればそれを達成できますか?
回答:
クリック状態とクリックされていない状態のさまざまな画像をデザインし、次のようにonTouchListenerで設定できます。
final ImageView v = (ImageView) findViewById(R.id.button0);
v.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.setImageBitmap(res.getDrawable(R.drawable.img_down));
break;
}
case MotionEvent.ACTION_CANCEL:{
v.setImageBitmap(res.getDrawable(R.drawable.img_up));
break;
}
}
return true;
}
});
より良い選択は、セレクターを次のように定義することです。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="@drawable/img_down" />
<item android:state_selected="false"
android:drawable="@drawable/img_up" />
</selector>
イベントで画像を選択します。
v.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
v.setSelected(arg1.getAction()==MotionEvent.ACTION_DOWN);
return true;
}
});
MotionEvent.ACTION_DOWN || MotionEvent.ACTION_MOVE
限り、私たちが押しているとして示す画像を維持します。
setOnTouchListener(...
。を作成して<selector ...>
から、次のようにXMLでクリック可能なImageViewを設定できます<ImageView ... android:clickable="true" android:focusable="true" android:src="@drawable/my_selector" />
次のようなものを使用して、単一の画像でこれを行うことができます。
//get the image view
ImageView imageView = (ImageView)findViewById(R.id.ImageView);
//set the ontouch listener
imageView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
ImageView view = (ImageView) v;
//overlay is black with transparency of 0x77 (119)
view.getDrawable().setColorFilter(0x77000000,PorterDuff.Mode.SRC_ATOP);
view.invalidate();
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
ImageView view = (ImageView) v;
//clear the overlay
view.getDrawable().clearColorFilter();
view.invalidate();
break;
}
}
return false;
}
});
再利用を容易にするために、これをImageViewのサブクラス(またはImageViewのサブクラスでもあるImageButton)にする予定ですが、これにより、「選択された」外観をimageviewに適用できるようになります。
false
。そうしないと、ビューの実際のonClick()
イベントが発生しません
1つの画像ファイルで行うことが可能ですColorFilterメソッドを使用してです。ただし、ColorFilterはボタンではなくImageViewで機能することを想定しているため、ボタンをImageViewに変換する必要があります。とにかく画像をボタンとして使用している場合、これは問題ではありませんが、テキストがある場合はさらに厄介です...とにかく、テキストの問題を回避する方法を見つけたと仮定して、使用するコードは次のとおりです。
ImageView button = (ImageView) findViewById(R.id.button);
button.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY);
これにより、ボタンに赤のオーバーレイが適用されます(カラーコードは完全に不透明な赤の16進コードです。最初の2桁は透明で、次にRR GG BBです)。
編集:以下の元の回答は機能し、設定も簡単ですが、より効率的な実装が必要な場合は、GoogleのAndroid DeveloperAdvocateによるこの投稿を参照してください。また、Android Mでは、デフォルトでImageViewを含むすべてのビューにandroid:foreground
属性が適用されることに注意してください。
ImageViewにセレクターを使用する場合の問題は、ビューの背景としてのみ設定できることです。画像が不透明である限り、その背後にセレクターの効果は表示されません。
秘訣は、ImageViewをそのコンテンツのオーバーレイandroid:foreground
を定義できる属性を使用してFrameLayoutでラップすることです。セレクター(APIレベル11以降など)に設定し、android:foreground
?android:attr/selectableItemBackground
OnClickListener
、ImageViewではなくFrameLayoutにと、画像はセレクターのドローアブル(必要なクリック効果)でオーバーレイされます。
見よ:
<FrameLayout
android:id="@+id/imageButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?android:attr/selectableItemBackground" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/yourImageFile" />
</FrameLayout>
(これは親レイアウト内に配置する必要があることに注意してください。)
final View imageButton = findViewById(R.id.imageButton);
imageButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
// do whatever we wish!
}
});
selectableItemBackground
属性はAPIレベル11でのみ追加されたため、古いAPIレベルでこのソリューションを使用する場合は、別のセレクターを使用する必要があります。たとえば、APIレベル7をサポートするアプリケーションの1つでは@drawable/list_selector_holo_light
、Android Holo ColorsGeneratorツールを使用して生成されたリソースを使用します。
<ImageButton>
selectableItemBackgroundで1つだけを使用して、同じ動作を実現できます。
使用スタイル=「アンドロイド:?borderlessButtonStyle」 XMLファイルインチ Androidのデフォルトのクリック効果が表示されます。
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
style="?android:borderlessButtonStyle"
/>
android:adjustViewBounds="true"
、パディングの設定を解除するために使用します。
style="?android:attr/borderlessButtonStyle"
:developer.android.com/guide/topics/ui/controls/...を
ImageButtonを使用するだけです。
これを解決する簡単な方法は次のとおりです。
ImageView iv = (ImageView) findViewById(R.id.imageView);
iv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//Agrega porcentajes de cada fraccion de grafica pastel
Animation animFadein = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fade_in);
iv.startAnimation(animFadein);
});
ファイル内res/anim/fade_in.xml
:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true" >
<alpha
android:duration="100"
android:fromAlpha="0.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
</set>
選択可能な背景をImageViewに設定し、パディングを追加します。次に、を添付しOnClickListener
ます。
<ImageView
android:id="@+id/your_image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/your_image"
android:padding="10dp"
android:background="?android:attr/selectableItemBackground"/>
セレクターの描画可能な選択肢を定義するため
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="@drawable/img_down" />
<item android:state_selected="false"
android:drawable="@drawable/img_up" />
</selector>
android:state_selectedの代わりにandroid:state_pressedを使用する必要があります
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed ="true"
android:drawable="@drawable/img_down" />
<item android:state_pressed ="false"
android:drawable="@drawable/img_up" />
</selector>
android:background="@android:drawable/list_selector_background"
デフォルトの「目覚まし時計」(現在は卓上時計)の「アラームの追加」と同じ効果を試してみることができます。
タップしたときにリップルが必要な場合は、次のコードで指定できます。
<ImageView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</ImageView>
同様に、TextViewのクリック効果を実装できます
<TextView
...
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
...
</TextView>
これは私のために働いた:
img.setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
((ImageView)v).setImageAlpha(200);
break;
}
case MotionEvent.ACTION_MOVE:
{
// if inside bounds
if(event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0 && event.getY() < v.getHeight())
{
((ImageView)v).setImageAlpha(200);
}
else
{
((ImageView)v).setImageAlpha(255);
}
break;
}
case MotionEvent.ACTION_UP:
{
((ImageView)v).setImageAlpha(255);
}
}
return true;
}
});
@Edit:Gunhanが言ったように、setImageAlphaメソッドには下位互換性の問題があります。私はこの方法を使用しました:
public static void setImageAlpha(ImageView img, int alpha)
{
if(Build.VERSION.SDK_INT > 15)
{
img.setImageAlpha(alpha);
}
else
{
img.setAlpha(alpha);
}
}
私はいくつかの同様のことをしますあなたに適しているかどうかを参照してください
プレスエフェクトヘルパーの表示:
使用法:iOSのような簡単なプレス効果を実行します
簡単な使用法:
ImageView img =(ImageView)findViewById(R.id.img);
上記のすべての回答と組み合わせて、ImageViewを押して状態を変更したかったのですが、ユーザーが移動した場合は「キャンセル」し、onClickListenerを実行しません。
最終的に、クラス内にPointオブジェクトを作成し、ユーザーがImageViewを押したときに従ってその座標を設定しました。MotionEvent.ACTION_UPで、新しいポイントを記録し、ポイントを比較しました。
私はそれをとてもうまく説明することができるだけです、しかしこれが私がしたことです。
// set the ontouch listener
weatherView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// Determine what action with a switch statement
switch (event.getAction()) {
// User presses down on the ImageView, record the original point
// and set the color filter
case MotionEvent.ACTION_DOWN: {
ImageView view = (ImageView) v;
// overlay is black with transparency of 0x77 (119)
view.getDrawable().setColorFilter(0x77000000,
PorterDuff.Mode.SRC_ATOP);
view.invalidate();
p = new Point((int) event.getX(), (int) event.getY());
break;
}
// Once the user releases, record new point then compare the
// difference, if within a certain range perform onCLick
// and or otherwise clear the color filter
case MotionEvent.ACTION_UP: {
ImageView view = (ImageView) v;
Point f = new Point((int) event.getX(), (int) event.getY());
if ((Math.abs(f.x - p.x) < 15)
&& ((Math.abs(f.x - p.x) < 15))) {
view.performClick();
}
// clear the overlay
view.getDrawable().clearColorFilter();
view.invalidate();
break;
}
}
return true;
}
});
imageViewにonClickListenerを設定していますが、これはメソッドにすることができます。
MotionEvent.ACTION_CANCEL
それと同じ機能を持つケースを追加することによりMotionEvent.ACTION_UP
、ユーザーがクリックアクションではない「ドラッグ」を実行した場合にビューを「クリア」することが可能です。
setPressed
onTouchEventリスナーを作成する代わりに、ImageViewでオーバーライドして、そこでカラーフィルタリングを実行できます。
@Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
if(getDrawable() == null)
return;
if(pressed) {
getDrawable().setColorFilter(0x44000000, PorterDuff.Mode.SRC_ATOP);
invalidate();
}
else {
getDrawable().clearColorFilter();
invalidate();
}
}
Zorn氏の回答に基づいて、抽象Utilityクラスで静的メソッドを使用します。
public abstract class Utility {
...
public static View.OnTouchListener imgPress(){
return imgPress(0x77eeddff); //DEFAULT color
}
public static View.OnTouchListener imgPress(final int color){
return new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN: {
ImageView view = (ImageView) v;
view.getDrawable().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
view.invalidate();
break;
}
case MotionEvent.ACTION_UP:
v.performClick();
case MotionEvent.ACTION_CANCEL: {
ImageView view = (ImageView) v;
//Clear the overlay
view.getDrawable().clearColorFilter();
view.invalidate();
break;
}
}
return true;
}
};
}
...
}
次に、onTouchListenerで使用します。
ImageView img=(ImageView) view.findViewById(R.id.image);
img.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { /* Your click action */ }
});
img_zc.setOnTouchListener(Utility.imgPress()); //Or Utility.imgPress(int_color_with_alpha)
画像がたくさんあり、XML描画可能で、画像が1つしかない、単純なonTouch効果が必要な場合は非常に簡単です。
を使用しandroid.widget.Button
、そのbackground
プロパティをに設定しますandroid.graphics.drawable.StateListDrawable
。これはすべてXMLで、またはプログラムで実行できます。フォームスタッフチュートリアルのカスタムボタンセクションを参照してください。
ここでサンプルを作成します。レイアウトからImageViewをClickableImageViewに変更するだけです。お役に立てば幸いです。
あなたが背景画像を使用する場合、私はより美しい解決策を持っています:)
public static void blackButton(View button){
button.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.getBackground().setColorFilter(0xf0f47521,PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP: {
v.getBackground().clearColorFilter();
v.invalidate();
break;
}
}
return false;
}
});
}
または:
このフォームは、画像ボタンで使用できます。
ファイルの作成res/drawable/btn_video.xml
:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/image"
android:state_pressed="true" />
<item android:drawable="@drawable/ico2"
android:state_focused="true" />
<item android:drawable="@drawable/ico2" />
</selector>
そしてres/layout/activity_main.xml
:
<ImageButton
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/imageButton"
android:layout_gravity="center_horizontal"
android:onClick="eventImageBtn"
android:background="@drawable/btn_video"
android:adjustViewBounds="true"
android:scaleType="fitXY"
/>
クリックするだけで画像が変化し、線形レイアウトで調整できます。
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/menu_item_background">
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"
android:paddingLeft="@dimen/main_screen_side_padding" android:paddingRight="@dimen/main_screen_side_padding" android:paddingTop="@dimen/main_screen_side_padding" android:paddingBottom="@dimen/main_screen_side_padding"
android:background="#ffb3ff13" android:weightSum="10.00">
<LinearLayout android:layout_weight="2.50" android:background="#ff56cfcd" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" >
<ImageButton
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/imageButton"
android:layout_gravity="center_horizontal"
android:onClick="eventImageBtn"
android:background="@drawable/btn_video"
android:adjustViewBounds="true"
android:scaleType="fitXY"
/>
</LinearLayout>
<LinearLayout android:layout_weight="0.50" android:layout_height="0dp" android:background="#ffffffff" android:orientation="vertical" android:layout_width="fill_parent" >
</LinearLayout>
<LinearLayout android:layout_weight="4.50" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" android:background="#ff8aa5ff">
</LinearLayout>
<LinearLayout android:layout_weight="0.50" android:layout_height="0dp" android:background="#ffffffff" android:orientation="vertical" android:layout_width="fill_parent" >
</LinearLayout>
<LinearLayout android:layout_weight="2.00" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="0dp" android:background="#ffff7d1a" >
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
これが私のソリューションで、「nineOldAndroids」ライブラリを使用して、古いAPIもサポートしています。
rootView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(final View v, final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
v.setBackgroundResource(R.drawable.listview_normal);
ViewHelper.setAlpha(imageView, 1);
break;
case MotionEvent.ACTION_DOWN:
v.setBackgroundResource(0);
v.setBackgroundColor(getResources().getColor(R.color.listview_pressed));
ViewHelper.setAlpha(imageView, 0.75f);
break;
}
return false;
}
});
rootViewはセル自体(レイアウト)であり、セル全体に適用する色の影響を受けたい単一のimageViewがあることを前提としています。
編集:必要に応じて、ImageViewを拡張してフォアグラウンドを処理し、「?android:attr / selectableItemBackground」に設定することもできます。このためのライブラリがここにあり、希望するビューに対してそれを行う方法のチュートリアルがここにあります。
このスレッドの助けをありがとう。ただし、1つ見逃したことがあります... ACTION_CANCELも処理する必要があります。そうしないと、ビュー階層の親ビューがタッチイベントをインターセプトした場合にImageViewのアルファ値を適切に復元できない可能性があります(ImageViewをラップするScrollViewを考えてください)。
これは、上記のクラスに基づいているが、ACTION_CANCELも処理する完全なクラスです。ImageViewCompatヘルパークラスを使用して、前後のJellyBeanAPIの違いを抽象化します。
public class ChangeAlphaOnPressedTouchListener implements OnTouchListener {
private final float pressedAlpha;
public ChangeAlphaOnPressedTouchListener(float pressedAlpha) {
this.pressedAlpha = pressedAlpha;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
ImageView iv = (ImageView) v;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ImageViewCompat.setAlpha(iv, pressedAlpha);
break;
case MotionEvent.ACTION_MOVE:
if (isInsideViewBounds(v, event)) {
ImageViewCompat.setAlpha(iv, pressedAlpha);
} else {
ImageViewCompat.setAlpha(iv, 1f);
}
break;
case MotionEvent.ACTION_UP:
ImageViewCompat.setAlpha(iv, 1f);
break;
case MotionEvent.ACTION_CANCEL:
ImageViewCompat.setAlpha(iv, 1f);
}
return false;
}
private static boolean isInsideViewBounds(View v, MotionEvent event) {
return event.getX() > 0 && event.getX() < v.getWidth() && event.getY() > 0
&& event.getY() < v.getHeight();
}
}
これが私のコードです。ImageViewは、ユーザーがタッチするとカラーフィルターを取得し、ユーザーがタッチを停止するとカラーフィルターが削除されるという考え方です。
Martin Booka Weser、András、Ah Lam、altosh、ImageViewにもonClickEventがある場合、ソリューションは機能しません。worawee.sおよびkcoppock(ImageButtonを使用)ソリューションには背景が必要ですが、ImageViewが透明でない場合は意味がありません。
これは、カラーフィルターに関するAZ_のアイデアの拡張です。
class PressedEffectStateListDrawable extends StateListDrawable {
private int selectionColor;
public PressedEffectStateListDrawable(Drawable drawable, int selectionColor) {
super();
this.selectionColor = selectionColor;
addState(new int[] { android.R.attr.state_pressed }, drawable);
addState(new int[] {}, drawable);
}
@Override
protected boolean onStateChange(int[] states) {
boolean isStatePressedInArray = false;
for (int state : states) {
if (state == android.R.attr.state_pressed) {
isStatePressedInArray = true;
}
}
if (isStatePressedInArray) {
super.setColorFilter(selectionColor, PorterDuff.Mode.MULTIPLY);
} else {
super.clearColorFilter();
}
return super.onStateChange(states);
}
@Override
public boolean isStateful() {
return true;
}
}
使用法:
Drawable drawable = new FastBitmapDrawable(bm);
imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5));
私は試してみました:
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/get_started"
android:src="@drawable/home_started"
style="?android:borderlessButtonStyle"
android:adjustViewBounds="true"
android:clickable="true"
android:elevation="5dp"
android:longClickable="true" />
そしてこれはうまくいった。次の行に注意してください。style="?android:borderlessButtonStyle"
最も簡単な方法は、新しいXMLファイルを作成することだと思います。この場合、drawableフォルダーで「example.xml」と呼び、次のコードを挿入します。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/blue"
android:state_pressed="true" />
</selector>
ただし、その前に、valuesフォルダーのcolors.xmlファイルで次のように色を設定する必要があります。
<resources>
<color name="blue">#0000FF</color>
</resources>
これで、次のように、新しいレイアウトを使用するようにButton / ImageButtonを設定するだけです。
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/example"
/>
次に、その画像をクリックすると、で設定された色に変わります
<item android:drawable="@color/blue"
android:state_pressed="true" />
あなたが望むフィードバックを与える...
これは私が今まで見た中で最高の解決策です。そのより一般的な。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true" >
<alpha
android:duration="100"
android:fromAlpha="0.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
</set>
今のところ、マテリアルデザインの実践を発展させる必要があります。この場合、ImageViewに波及効果を追加できます。
XML属性、android:clickable = "true" ..を追加するだけです。