Bouton De Forme Personnalisé Pour Android

Comment puis-je faire une vue ou un bouton personnalisé cliquable sur Android?

Quand je clique , je veux éviter de toucher sur une zone vide .

enter image description here

s'il vous plaît aider. Remercier.

40
demandé sur Erhan Demirci 2012-12-13 18:00:53

8 réponses

question intéressante. J'ai essayé quelques solutions et c'est ce que j'ai trouvé qui a le même résultat de ce que vous essayez d'atteindre. La solution ci-dessous résout 2 problèmes:

  1. forme Personnalisée comme vous l'avez présenté
  2. le côté droit supérieur du bouton ne doit pas être cliquable

ainsi c'est la solution en 3 étapes:

Étape 1

crée deux formes.

  • première forme rectangulaire simple pour le bouton: 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>
    
  • deuxième forme est utilisée comme masque pour le côté supérieur droit du bouton: shape_button_beer_mask.xml . C'est cercle simple avec la couleur noire solide.

    <?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>
    

l'Étape 2

dans votre ajouter le bouton par l'approche suivante:

  • RelativeLayout est le conteneur de ce bouton personnalisé
  • premier affichage en ligne est le bouton bleu avec l'icône de la bière et le texte à l'intérieur
  • Deuxième ImageView est le masque au-dessus du bouton bleu. Et voici sale truc:
    1. les marges sont négatives pour placer le masque au bon endroit
    2. nous définissons id pour pouvoir Outrepasser le clic (voir étape 3)
    3. android:soundEffectsEnabled="false" - tel que l'utilisateur ne sentira pas qu'il a appuyé sur quelque chose.

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 -->

Étape 3

dans votre activité principale vous définissez sur les événements de clic à la fois: bouton et le masque comme suit:

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
    }
});

C'est ça. Je sais que ce n'est pas une solution parfaite, mais dans le cas d'utilisation décrit, cela pourrait aider. J'ai testé sur mon mobile et c'est à quoi il ressemble quand vous cliquez sur la zone bleue et rien ne se passera sur d'autres zones:

  • enter image description here

Espérons qu'il a aidé en quelque sorte :)

38
répondu sromku 2012-12-14 13:20:52

utilisez OnTouch au lieu de OnClick et vérifiez la valeur alpha de l'image que vous avez utilisée dans le bouton.Si ce n'est pas égal à zéro, faites ce que vous voulez. Vérifiez le code suivant,

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;
}
14
répondu Basim Sherif 2013-01-25 07:32:14

u peut essayer celui-ci:

        <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"/>

et créer rond.fichier xml dans le dossier dessiner:

        <?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>
3
répondu G M Ramesh 2012-12-14 09:47:53

utiliser layer-list, Vous pouvez concevoir n'importe quelle forme n'importe quel sommet de bouton de pente voici l'exemple

<?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> 

valeurs du rayon d'utilisation pour obtenir la forme du bouton comme indiqué par u

3
répondu Charan Pai 2012-12-14 09:52:43

j'ai eu un problème similaire mais je ne voulais pas dépendre du code derrière pour examiner la valeur du pixel. Je voulais un moyen simple (pas de surcharge de classe) pour limiter un événement touch à une sous-portion d'un drawable. Ci-dessous, j'utilise une sortie linéaire pour le drawable et puis à l'intérieur que j'ai mis un bouton transparent (avec du texte). Je peux ajuster la marge du bouton pour positionner la zone cliquable.

    <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>
1
répondu Mark Owens 2015-09-04 14:33:40

meilleure solution et plus facile (as4me) j'ai trouvé ici - il est sous-classé bouton et donc il soutient le sélecteur. Donc, tout ce que vous devez faire est de dessiner/ajouter pngs correspondants pour chaque État de bouton pour utiliser le sélecteur et déclarer onClick en xml ou ajouter OnClickListener en code et vous êtes prêt à aller.

0
répondu Stan 2017-05-23 12:18:30

plutôt que de faire tous ces changements, vous devriez utiliser la disposition du cadre à la partie qui entoure le bouton, et masquer la partie supérieure droite avec un peu de chose(circulaire, comme un bouton arrondi) et assigner aucun auditeur de clic sur cette partie. Cela cache en effet le cadre inférieur(c.-à-d. votre bouton original) et le masque avec la partie non active.

0
répondu Abhijeet Soni 2016-01-24 00:10:55

j'ai essayé la réponse de @Basim Sherif ( lien ) et cela fonctionne bien cependant seulement si la taille du bouton est la même que l'image originale. Si le bouton a été étiré jusqu'alors cliquable région sera plus petit et si le bouton a été mis à une plus petite taille de la cliquables région sera plus grand que le bouton.

la solution est simple qui consiste à mettre à l'échelle les valeurs iX et iY pour correspondre au bitmap original.

et voici ma version modifiée du code:

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;
}
0
répondu Fahad Alduraibi 2017-05-23 11:47:32