Android Custom Shape Button
Jak zrobić niestandardowy kształt klikalny widok lub przycisk w Androidzie?
Kiedy klikam, chcę uniknąć dotykania pustego obszaru .
Proszę o pomoc. Dziękuję.
8 answers
Ciekawe pytanie. Próbowałem kilku rozwiązań i to jest to, co znalazłem, że ma taki sam wynik, co próbujesz osiągnąć. Poniższe rozwiązanie rozwiązuje 2 problemy:
- Custom shape as you presented it
- prawy górny guzik nie powinien być klikalny
Więc jest to rozwiązanie w 3 krokach:
Krok 1
Utwórz dwa kształty.
-
Pierwszy prosty kształt prostokąta dla przycisku: 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>
-
Drugi kształt jest używany jako maska dla prawej górnej części przycisku: shape_button_beer_mask.xml . Jest to proste koło z czarnym jednolitym kolorem.
<?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>
Krok 2
W głównym układzie Dodaj przycisk przy następnym podejściu:
- RelativeLayout jest kontenerem tego niestandardowego przycisku
- pierwsza linia To niebieski przycisk z ikoną piwa i tekstem wewnątrz
- drugi ImageView to Maska nad niebieskim guzikiem. And here comes dirty trick:
- marginesy są ujemne, aby ustawić maskę we właściwym miejscu
- definiujemy id, aby móc nadpisać po kliknięciu (patrz krok 3)
-
android:soundEffectsEnabled="false"
- taki, że użytkownik nie będzie czuł, że na coś naciskał.
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 -->
Krok 3
W głównej aktywności definiujesz zdarzenia dla przycisku i maski w następujący sposób:
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
}
});
To wszystko. Wiem, że to nie jest idealne. rozwiązanie, ale w opisanym przypadku użycia może to pomóc.
Testowałem go na moim telefonie i tak wygląda po kliknięciu na niebieski obszar i nic się nie stanie na innych obszarach: {]}
Mam nadzieję, że jakoś pomogło:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-14 13:20:52
Użyj OnTouch zamiast OnClick i sprawdź wartość alfa obrazu używanego w przycisku.Jeśli nie równa się zero, rób co chcesz. Sprawdź followsig 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();
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-25 07:32:14
U można spróbować tego:
<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"/>
I utworzyć okrągły.plik xml w katalogu drawable:
<?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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-14 09:47:53
Użyj layer-list, możesz zaprojektować dowolny kształt dowolnego przycisku gradientu oto przykład
<?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>
Użyj wartości promienia-ve, aby nadać kształt przycisku tak, jak wspomniano u
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-14 09:52:43
Miałem podobny problem, ale nie chciałem polegać na kodzie za zbadać wartość piksela. Chciałem prosty sposób (nie przeciążenie klasy), aby ograniczyć Zdarzenie dotykowe tylko do części podrzędnej drawable. Poniżej używam LinearLayout do rysowania, a następnie w środku umieszczam przezroczysty przycisk (z tekstem). Mogę dostosować margines przycisku, aby ustawić klikalny obszar.
<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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-04 14:33:40
Najlepsze i najłatwiejsze rozwiązanie (as4me) znalazłem tutaj - jest to subklasowany przycisk {[2] } i dzięki temu obsługuje selektor. Wszystko, co musisz zrobić, to narysować / dodać odpowiednie pngs dla każdego stanu przycisku, aby użyć selektora i zadeklarować onClick w xml lub dodać OnClickListener w kodzie i jesteś gotowy do pracy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:30
Zamiast tych wszystkich zmian, powinieneś użyć układu ramki w części otaczającej przycisk i zamaskować górną prawą część jakimś czymś (okrągłym, jak zaokrąglony przycisk) i przypisać do tej części bez słuchacza kliknięć. To w efekcie ukrywa dolną ramkę (tj. oryginalny przycisk) i maskuje ją z nieaktywną częścią.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-24 00:10:55
Próbowałem odpowiedzieć przez @ Basim Sherif (link) i działa świetnie jednak tylko wtedy, gdy rozmiar przycisku jest taki sam jak oryginalnego obrazu. Jeśli przycisk został rozciągnięty, klikalny region będzie mniejszy, a jeśli przycisk został ustawiony na mniejszy rozmiar, klikalny region będzie większy niż rzeczywisty przycisk.
Rozwiązanie jest proste, polega na skalowaniu wartości iX i iY tak, aby pasowały do oryginalnej bitmapy.
A oto moja zmodyfikowana wersja kodu:
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:32