44

Androidでカスタム形状のクリック可能なビューまたはボタンを作成するにはどうすればよいですか?

クリックしたとき、何もない領域に触れないようにしたい。

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

助けてください。ありがとうございました。

4

8 に答える 8

40

興味深い質問です。私はいくつかの解決策を試しましたが、これはあなたが達成しようとしていることと同じ結果をもたらすことがわかりました。以下の解決策は、2つの問題を解決します。

  1. あなたがそれを提示したときのカスタム形状
  2. ボタンの右上はクリックできないようにする必要があります

したがって、これは3つのステップでの解決策です。

ステップ1

2つの形状を作成します。

  • ボタンの最初の単純な長方形の形状:shape_button_beer.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <gradient
            android:angle="90"
            android:endColor="#C5D9F4"
            android:startColor="#DCE5FD" />
    
        <corners
            android:bottomLeftRadius="5dp"
            android:bottomRightRadius="5dp"
            android:topLeftRadius="5dp" >
        </corners>
    
    </shape>
    
  • 2番目の形状は、ボタンの右上のマスクとして使用されます:shape_button_beer_mask.xml。黒無地のシンプルなサークルです。

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval" >
    
        <solid android:color="#000000" />
    
    </shape>
    

ステップ2

メインレイアウトで、次のアプローチでボタンを追加します。

  • RelativeLayoutは、このカスタムボタンのコンテナです
  • 最初のLinearLayoutは、ビールのアイコンとテキストが入った青いボタンです。
  • 2番目のImageViewは、青いボタンの上のマスクです。そして、ここに汚いトリックがあります:
    1. マスクを適切な場所に設定するためのマージンは負です
    2. クリック時にオーバーライドできるようにidを定義します(ステップ3を参照)
    3. android:soundEffectsEnabled="false"-ユーザーが何かを押したと感じないようにします。

XML:

    <!-- Custom Button -->
    <RelativeLayout
        android:layout_width="120dp"
        android:layout_height="80dp" >

        <LinearLayout
            android:id="@+id/custom_buttom"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/shape_button_beer" >

            <!-- Beer icon and all other stuff -->

            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginLeft="5dp"
                android:layout_marginTop="15dp"
                android:src="@drawable/beer_icon" />
        </LinearLayout>

        <ImageView
            android:id="@+id/do_nothing"
            android:layout_width="120dp"
            android:layout_height="100dp"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:layout_marginRight="-50dp"
            android:layout_marginTop="-50dp"
            android:background="@drawable/shape_button_beer_mask"
            android:soundEffectsEnabled="false" >
        </ImageView>
    </RelativeLayout>
    <!-- End Custom Button -->

ステップ3

メインアクティビティでは、ボタンとマスクの両方のクリックイベントを次のように定義します。

LinearLayout customButton = (LinearLayout) findViewById(R.id.custom_buttom);
customButton.setOnClickListener(new View.OnClickListener()
{
    @Override
    public void onClick(View arg0)
    {
        Toast.makeText(getApplicationContext(), "Clicked", Toast.LENGTH_SHORT).show();
    }
});

// Mask on click will do nothing
ImageView doNothing = (ImageView) findViewById(R.id.do_nothing);
doNothing.setOnClickListener(new View.OnClickListener()
{
    @Override
    public void onClick(View arg0)
    {
        // DO NOTHING
    }
});

それでおしまい。私はそれが完璧な解決策ではないことを知っていますが、あなたの説明したユースケースではそれが役立つかもしれません。私は自分の携帯電話でそれをテストしました、そしてこれはあなたが青い領域をクリックしたときそれがどのように見えるかです、そして他の領域では何も起こりません:

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

それが何らかの形で役に立ったことを願っています:)

于 2012-12-14T13:20:52.837 に答える
15

OnClickの代わりにOnTouchを使用して、ボタンで使用した画像のアルファ値を確認します。ゼロに等しくない場合は、必要な操作を行います。次のコードを確認してください。

final Bitmap bitmap;  //Declare bitmap     
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.TheImage);


public boolean onTouch(View v, MotionEvent event) {

        int eventPadTouch = event.getAction();
        float iX=event.getX();
    float iY=event.getY();

        switch (eventPadTouch) {

            case MotionEvent.ACTION_DOWN:
                if (iX>=0 & iY>=0 & iX<bitmap.getWidth() & iY<bitmap.getHeight()) { //Makes sure that X and Y are not less than 0, and no more than the height and width of the image.                
                    if (bitmap.getPixel((int) iX, (int) iY)!=0) {
                        // actual image area is clicked(alpha not equal to 0), do something 
                    }               
                }
                return true;                
        }           
        return false;
}
于 2013-01-25T06:32:44.497 に答える
3

あなたはこれを試すことができます:

        <Button
        android:id="@+id/logout"
        android:layout_width="240dp"
        android:layout_height="28dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="ContactsDetails"
        android:textColor="#ffffff" android:layout_marginLeft="50dp" android:background="@drawable/round"/>

ドローアブルフォルダにround.xmlファイルを作成します。

        <?xml version="1.0" encoding="utf-8"?>
      <shape xmlns:android="http://schemas.android.com/apk/res/android"
      android:shape="rectangle" android:padding="0dp" android:useLevel = "false">
    <!-- you can use any color you want I used here gray color-->
     <solid android:color="#ABABAB"/> 
       <corners
       android:bottomRightRadius="0dp"
         android:bottomLeftRadius="0dp"
       android:topLeftRadius="0dp"
      android:topRightRadius="70dp"/>
       </shape>
于 2012-12-13T14:10:57.463 に答える
3

レイヤーリストを使用して、任意の形状を設計できます。ここでは、グラデーションボタンの上部が例です。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle">
            <corners

                android:topLeftRadius="0dp"
                android:topRightRadius="0dp"
                android:bottomLeftRadius="2dp"
                android:bottomRightRadius="15dp"
                />            
            <!-- The border color -->
            <solid android:color="#ffffff" />
        </shape>
    </item>

    <item android:right="2dp"
        android:left="2dp"
        android:bottom="2dp">
            <shape>            
            <gradient                
                android:startColor="#002a36"
                android:centerColor="#457c8e"
                android:endColor="#e6ffff"               
                android:angle="90" 
                  android:centerY="1"
                android:centerX="0.5"           
                />          

            <corners

                android:topLeftRadius="0dp"
                android:topRightRadius="0dp"
                android:bottomLeftRadius="2dp"
                android:bottomRightRadius="15dp"
                />            
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" 
                />                        
        </shape>
    </item>
</layer-list> 

-veの半径値を使用して、uが述べたようにボタンの形状を作成します

于 2012-12-14T09:52:43.640 に答える
1

同様の問題が発生しましたが、ピクセル値を調べるためにコードビハインドに依存したくありませんでした。タッチイベントをドローアブルのサブ部分のみに制限する簡単な方法(クラスのオーバーロードではない)が必要でした。以下では、ドローアブルにLinearLayoutを使用し、その中に透明なボタン(テキスト付き)を配置します。ボタンの余白を調整して、クリック可能な領域を配置できます。

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:background="@drawable/circle">
        <Button
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:id="@+id/btnTimer1"
            android:text="0:00"
            android:textColor="#ffffff"
            android:textSize="22dp"
            android:layout_margin="20dp"
            android:background="@android:color/transparent"/>
    </LinearLayout>
于 2015-09-04T14:33:40.437 に答える
0

私がここで見つけた最良かつ最も簡単な解決策(as4me)-それはサブクラス化されたボタンであり、したがってセレクターをサポートします。したがって、必要なのは、セレクターを使用してxmlでonClickを宣言するか、コードでOnClickListenerを追加するために、ボタンの状態ごとに対応するpngを描画/追加することだけです。これで、準備が整います。

于 2013-11-19T16:03:18.170 に答える
0

これらすべての変更を行うのではなく、ボタンを囲む部分でフレームレイアウトを使用し、右上の部分を何か(丸いボタンのような円形)でマスクし、その部分にクリックリスナーを割り当てないようにする必要があります。これにより、実際には下部フレーム(つまり元のボタン)が非表示になり、非アクティブな部分でマスクされます。

于 2016-01-24T00:10:55.893 に答える
0

@Basim Sherif(リンク)で答えを試しましたが、ボタンのサイズが元の画像と同じである場合にのみうまく機能します。ボタンが引き伸ばされている場合、クリック可能な領域は小さくなり、ボタンが小さいサイズに設定されている場合、クリック可能な領域は実際のボタンよりも大きくなります。

解決策は単純で、元のビットマップに一致するようにiX値とiY値をスケーリングします。

そして、これが私の修正バージョンのコードです:

final Bitmap bitmap;  //Declare bitmap     
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.TheImage);

public boolean onTouch(View v, MotionEvent event) {

    int eventPadTouch = event.getAction();
    float iX=event.getX();
    float iY=event.getY();

    // Get the dimensions used in the view
    int realW = this.getWidth();
    int realH = this.getHeight();

    // Get the dimensions of the actual image
    int bitmapW = bitmap.getWidth();
    int bitmapH = bitmap.getHeight();

    // Scale the coordinates from the view to match the actual image
    float scaledX = iX * bitmapW / realW;
    float scaledY = iY * bitmapH / realH;

    switch (eventPadTouch) {
        case MotionEvent.ACTION_DOWN:
            if (scaledX >= 0 & scaledY >= 0 & scaledX < bitmap.getWidth() & scaledY < bitmap.getHeight()) { //Makes sure that X and Y are not less than 0, and no more than the height and width of the image.                
                if (bitmap.getPixel((int) scaledX, (int) scaledY)!=0) {
                    // actual image area is clicked(alpha not equal to 0), do something 
                }
            }
            return true;
    }
    return false;
}
于 2016-01-31T05:35:59.387 に答える