Androidでボタンクリック効果を設定する方法


105

Androidで、背景画像をボタンに設定すると、ボタンへの影響がわかりません。

ユーザーがボタンがクリックされたことを認識できるように、ボタンに何らかの効果が必要です。

クリックすると数秒間ボタンが暗くなるので、どうすればいいですか?

ありがとう。



以下の方法に関係なく、テキストの、あなたは肌にすべてのボタンを単一styleClassのを使用することができます:stackoverflow.com/questions/5327553/...
ザックMarrapese

いいえ、画像ボタンを使用していません。これには簡単な方法で通常ボタンを使用していますか。
ジグネシュアンソダリヤ2013

3
その非常に素晴らしいチュートリアル:dibbus.com/2011/02/gradient-buttons-for-android
Pratik Butani 2013年

回答:


154

これは、ボタンの状態のリストを含む描画可能なxmlファイルを作成することで実現できます。たとえば、次のコードで「button.xml」という新しいxmlファイルを作成するとします。

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/YOURIMAGE" />
    <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/gradient" />
    <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/gradient" />
    <item android:drawable="@drawable/YOURIMAGE" />
</selector>

プレス時に背景画像を暗くしたままにするには、2番目のxmlファイルを作成し、次のコードでgradient.xmlと名前を付けます。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <bitmap android:src="@drawable/YOURIMAGE"/>
    </item>
    <item>
        <shape xmlns:android="http://schemas.android.com/apk/res/android">
            <gradient android:angle="90" android:startColor="#880f0f10" android:centerColor="#880d0d0f" android:endColor="#885d5d5e"/>
        </shape>
    </item>
</layer-list>

ボタンのxmlで、背景をボタンのxmlに設定します。

android:background="@drawable/button"

お役に立てれば!

編集:上記のコードを変更して、ブロックの色ではなく画像(YOURIMAGE)をボタンに表示します。


次に、ボタンの背景に画像を設定できますが、画像を設定する必要があります
Jignesh Ansodariya

1
状態XMLで背景画像を使用する方法を示すために編集されました。YOURIMAGEをドローアブルディレクトリ内の画像リソースに置き換えます。
Ljdawson、2011

これは、ボタンのソースが長方形の場合にのみ機能します。srcドローアブルの形状がそれと異なる場合、グラデーションも背景に適用されます。これは悲しいことです。
Renato Lochetti、2013年

実際はそうではありませんが、レイヤーリストで常に別の形状を使用することができました
Ljdawson

2
画像を使用している間は問題なく動作しますが、Xmlの背景を使用している場合は、機能していません...
DKV、2015年

88

画像ボタンがたくさんあり、すべてのボタンにxml-sを記述したくない場合は、より簡単です。

Kotlinバージョン:

fun buttonEffect(button: View) {
    button.setOnTouchListener { v, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                v.background.setColorFilter(-0x1f0b8adf, PorterDuff.Mode.SRC_ATOP)
                v.invalidate()
            }
            MotionEvent.ACTION_UP -> {
                v.background.clearColorFilter()
                v.invalidate()
            }
        }
        false
    }
}

Javaバージョン:

public static void buttonEffect(View button){
    button.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.getBackground().clearColorFilter();
                    v.invalidate();
                    break;
                }
            }
            return false;
        }
    });
}

2
私はこれをコードで使用していますが、これまでに気付いた唯一の問題は、ScrollViewに配置したときにボタンが奇妙に動作することです。
Finnboy11 2013年

それは本当に素晴らしい解決策であり、これは正解であるはずです
Biraj Zalavadia 14

これはどうですか?設計はコードの外で行われるべきですよね。
バグが発生する

この問題の簡単な解決策です。ボタンがたくさんあり、ボタンごとにxmlを作成したくない場合は、それが役立つでしょう。
アンドラス、2015年

ああ、神様!フラグメントに5つのボタンがあると想像してみてください...このボイラープレートコードはたくさんあります...それをリファクタリングする方法は?すべてのアクティビティのすべてのボタンのカラーフィルターを変更しますか?Imhoそれはあなたの次の開発者はそれほど幸せではないでしょう..
Leo Droidcoder '21

84

AlphaAnimationボタンのフェード効果の程度を決定するオブジェクトを作成し、ボタンので開始させonClickListenerます

例えば ​​:

private AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);

// some code

public void onClick(View v) {
    v.startAnimation(buttonClick);
}

もちろん、これは単なる方法であり、最も好ましい方法ではありません。


5
このソリューションについて私が気に入っているのは、独自のカスタム画像を持つボタンが多数ある場合に、多くのセレクターを作成する必要がないことです。
ピート

2
これはタッチダウン時にボタンをフェードしません。クリックが検出されてユーザーの指がすでに離された後、1秒間だけボタンをフェードします。
Doug Voss

1

@Doug Voss、アニメーションの継続時間を設定して、アニメーションを長くすることができます
Ahmed Adel Ismail

onLongClickと 'circularReveal'はどうですか?
–AcauãPitta 2019

44

フォアグラウンドを単純に使用Viewして、クリック可能な効果を実現できます。

android:foreground="?android:attr/selectableItemBackground"


暗いテーマで使用する場合も、追加のテーマをあなたにlayout(明確にするクリッカブル効果):

android:theme="@android:style/ThemeOverlay.Material.Dark"

5
実装する最も簡単な方法。前景はAPIレベルには影響を与えません23.より低い:FYI、属性は、Android
dolgom

1
最も簡単なソリューション。
ジェリーチョン

2
これは、受け入れられる答えであり、はるかに単純で、素晴らしいリップルアニメーション効果を追加します。
タイラー

1
@dolgom APIレベル<23の場合は、「background」属性で使用します。So:android:background = "?android:attr /
selectableItemBackground

24

アイテムをシステムのルックアンドフィールと一致させるにandroid:attr/selectableItemBackgroundは、目的のビューの背景タグまたは前景タグでシステム属性を参照してみてください。

<ImageView
    ...
    android:background="?android:attr/selectableItemBackground"      
    android:foreground="?android:attr/selectableItemBackground"
    ...
/>

両方の属性を使用して、APIレベル23の前または後のそれぞれで目的の効果を得る

https://stackoverflow.com/a/11513474/4683601


2
はるかに簡単なソリューションです。ありがとう!
tykom

9

または、背景画像を1つだけ使用して、クリック効果を実現できます。 setOnTouchListener

二つの方法

((Button)findViewById(R.id.testBth)).setOnTouchListener(new OnTouchListener() {

      @Override
        public boolean onTouch(View v, MotionEvent event) {
          switch (event.getAction()) {
              case MotionEvent.ACTION_DOWN: {
                  Button view = (Button) v;
                  view.getBackground().setColorFilter(0x77000000, PorterDuff.Mode.SRC_ATOP);
                  v.invalidate();
                  break;
              }
              case MotionEvent.ACTION_UP:
                  // Your action here on button click
              case MotionEvent.ACTION_CANCEL: {
                  Button view = (Button) v;
                  view.getBackground().clearColorFilter();
                  view.invalidate();
                  break;
              }
          }
          return true;
        }
});

ここに画像の説明を入力してください

を使用したくない場合setOnTouchLister、これを達成する別の方法は

    myButton.getBackground().setColorFilter(.setColorFilter(0xF00, Mode.MULTIPLY);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {android.R.attr.defaultValue}, myButton);

    myButton.setBackgroundDrawable(listDrawable);

2番目の方法でコードにエラーがあります。getCurrent()関数とは何ですか?また、myButtonはDrawableではないため、状態として追加できません。
Ehtesham Hasan

エラーを指摘していただきありがとうございます。私はそれを修正しました。myButtonは、setBackgroundDrawableメソッドを提供するButtonクラスのインスタンスであり、Drawableインスタンスを取得するため、これは機能します。
Vinayak Bevinakatti 2016

あなたの2番目のアプローチに基づいた私の答えをチェックしてください。stackoverflow.com/a/39430738/5229515
Ehtesham Hasan

これはおそらくイベントを消費せず、追加のonClickListenersを呼び出すことができるように、末尾に「return false」があるはずです。
Doug Voss 2017

3

これを行う別の簡単な方法を追加したいだけです:ImageButtonが背景のままで、nullに設定しない場合、通常のボタンのように機能し、クリックアニメーションを表示しながら、他のボタンとまったく同じようにクリックします。非表示にする方法まだそこにある間の背景:

<ImageButton
    android:id="@+id/imageButton2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingBottom="1dp"
    android:paddingLeft="1dp"
    android:paddingRight="1dp"
    android:paddingTop="1dp"
    android:src="@drawable/squareicon" />

パディングでは背景が表示されず、ボタンは他のボタンのように機能します。


1
これにより、円形の場合、四角いボタンの境界線が画像の周囲に保持されます
MSaudi

3

これは、@ Vinayakの答えからヒントを得ることを思いついた最良の解決策です。他のすべてのソリューションには、さまざまな欠点があります。

まず、このような関数を作成します。

void addClickEffect(View view)
{
    Drawable drawableNormal = view.getBackground();

    Drawable drawablePressed = view.getBackground().getConstantState().newDrawable();
    drawablePressed.mutate();
    drawablePressed.setColorFilter(Color.argb(50, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);

    StateListDrawable listDrawable = new StateListDrawable();
    listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
    listDrawable.addState(new int[] {}, drawableNormal);
    view.setBackground(listDrawable);
}

説明:

getConstantState()。newDrawable()は、既存のDrawableを複製するために使用されます。それ以外の場合は、同じDrawableが使用されます。続きを読む: Android:フィルターを使用してStateListDrawableを作成するために、Drawableを複製する

mutate()は、Drawableクローンがその状態をDrawableの他のインスタンスと共有しないようにするために使用されます。詳しくは、https//developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate()をご覧ください。

使用法:

任意のタイプのビュー(Button、ImageButton、Viewなど)をパラメーターとして関数に渡すと、クリック効果が適用されます。

addClickEffect(myButton);
addClickEffect(myImageButton);

2
Step: set a button in XML with onClick Action:

 <Button
android:id="@+id/btnEditUserInfo"
style="?android:borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="@dimen/txt_height"
android:layout_gravity="center"
android:background="@drawable/round_btn"
android:contentDescription="@string/image_view"
android:onClick="edit_user_info"
android:text="Edit"
android:textColor="#000"
android:textSize="@dimen/login_textSize" />

Step: on button clicked show animation point
//pgrm mark ---- ---- ----- ---- ---- ----- ---- ---- -----  ---- ---- -----

    public void edit_user_info(View view) {

        // show click effect on button pressed
        final AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);
        view.startAnimation(buttonClick);

        Intent intent = new Intent(getApplicationContext(),  EditUserInfo.class);
        startActivity(intent);

    }// end edit_user_info

2

マテリアルデザインの状態の押された/クリックされた効果にRippleDrawableを使用します。

これを実現するには、/ drawableフォルダーの下に.xmlとしてリップルアイテムを作成し、ビューのandroid:backgroundで使用します。

  • 押された/クリックされたアイコンの効果。たとえば、円形の波紋効果を使用します。

    <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@android:color/darker_gray" />

  • 長方形の境界でクリックされたビューの効果、以下のような既存のドローアブルに波紋を追加できます。

    <?xml version="1.0" encoding="utf-8"?> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#000000"> <item android:drawable="@drawable/your_background_drawable"/> </ripple>


2

すべてのビュー

android:background="?android:attr/selectableItemBackground"

しかし、高度を使用するカードビューの場合

android:foreground="?android:attr/selectableItemBackground"

ツールバーのような円形クリック効果の場合

android:background="?android:attr/actionBarItemBackground"

また、設定する必要があります

 android:clickable="true"
 android:focusable="true"

0

アンドラスの答えに少し追加します:

を使用postDelayedして、カラーフィルターを短期間持続させて、より目立たせることができます。

        @Override
        public boolean onTouch(final View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    v.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
                    v.invalidate();
                    break;
                }
                case MotionEvent.ACTION_UP: {
                    v.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            v.getBackground().clearColorFilter();
                            v.invalidate();
                        }
                    }, 100L);
                    break;
                }
            }
            return false;
        }

必要に応じて、ディレイ100Lの値を変更できます。


0

IMGの代わりにxml backgroundを使用している場合は、これを削除してください:

<item>
    <bitmap android:src="@drawable/YOURIMAGE"/>
</item>

@Ljdawsonがくれた最初の答えから。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.