Aklımda Kalası Kelimeler

* давайте работать вместе
* Zarf ve Mazruf, Zerafet(xHoyratlık) ile aynı kökten(za-ra-fe) gelir
* Bedesten
* Suç subuta ermiştir - Suç sabit olmuştur

23 Temmuz 2011 Cumartesi

Özelleştirilmiş android butonu tasarlamak

Yapmak istediğimiz düğme aşağıdaki gibi. 1inci resim tıklamadan, 2inci resim tıkladıktan sonraki hali (default, pressed).



Düğmemiz android sdk sından çıkan ilk haliyle şöyledir:
<Button
android:id="@+id/cust_button"
android:text="Özel Düğme"
android:layout_width="match_parent"
android:layout_height="wrap_content" />


Button etiketi içine text özellikleri vs. ekleyelim.
      <Button
android:id="@+id/cust_button"
android:text="Özel Düğme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:color="#444"
android:radius="18dp"
android:textColor="#ff0000"
android:gravity="center"
android:textSize="30dp"
android:textStyle="bold"
android:shadowColor="#ff00ff"
android:shadowDx="1"
android:shadowDy="2"
android:shadowRadius="3" />

Bu güzel oldu ama main.xml layout dosyamız çok kabardı ve her yeni butona bu özellikler(xml attributes) eklemek istemeyiz. Hem köşeleri hafif oval, kenarlıklı ve basıldığında başka bir görüntüsü olan buton istiyoruz. Bu durumla başa çıkmak için android:background, android:textColor, style xml özellikleri(attributes) kullanabiliriz. android:background butonumuzun kavislerini, kenarlıklarını ve varsayılan, basılı ve odaklandığında(focus-bir elemente tab ile ya da fare ile(burada parmağımız) tıklandığında) alacağı halleri tutan xml dosyamızı oluşturmalıyız. Ama önce basıldığında, varsayılan, odaklanıldığında gibi halleri(state) anlayalım.

android:background


Android de View'dan türetilmiş elemanların aşağıdaki durumları vardır:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:color="hex_color"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_window_focused=["true" | "false"] />
</selector>

Yukarıdaki durumlardan bizim düğmemiz(button) için geçerli olan android:state_focused ve android:state_pressed durumlarını ele alacağız.

Düğmemiz için yukarıdaki durumlarda nasıl görünmesini istiyorsak bunları res/drawable klasörüne xxxx.xml dosyası adında oluşturacağız:Bu dosya düğmemizin arka plan görüntüleri için kullanılacak.

Düğmemize basmadık; o zaman "pressed" durumuna girmeyiz, e focus'ta olmadığımıza göre default durumuna kadar geldik ve bu durumdaki şekili giydirmiş olacağız düğmemize. Akış bu şekilde olduğu için ilk denk geldiği durumu işleyecek bu yüzden en olmadığı en üste ve en varsayılan durumu ise en alta koyacağız.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<!-- pressed: the first item in the state list that matches the current state -->
<item android:state_pressed="true" ></item>

<!-- focused -->
<item android:state_focused="true" ></item>

<!-- default: value should always be last -->
<item></item>
</selector>



Varsayılan(default) durum yani düğmemizin kendi başına mel mel bakındığı durumu::
<!-- default -->
<item>
<shape>
<!-- Opak olarak beyaz (#fff) arka plan -->
<solid android:color="#fff"/>
<!-- Kenarlık diye 1px #ff007f renginde(stroke) -->
<stroke android:width="1px" android:color="#ff007f" />
<!-- Köşeler 18dp çapında yuvarlansın -->
<corners android:radius="18dp" />
</shape>
</item>


Artık diğer durumlarıda xml dosyamıza ekleyelim. FOCUS olduğunda ya da PRESSED olduğunda kenarlık rengini #444 rengine çekelim ve arka plan renginide geçişli(gradient) renk olarak boyayalım(startColor="#3787ff" endColor="#2f72d7" angle="270") ve dosyamızın son halini görelim:
cust_btn_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<!-- pressed -->
<item android:state_pressed="true" >
<shape>
<stroke android:width="1px" android:color="#444" />
<corners android:radius="18dp" />
<gradient android:startColor="#3787ff" android:endColor="#2f72d7" android:angle="270" />
<corners android:radius="18dp" />
<!-- Düğmenin arka rengini tek renk yapmak istersek: -->
<!-- solid android:color="#ffff00" kullanırız -->
</shape>
</item>

<!-- focused -->
<item android:state_focused="true" >
<shape>
<stroke android:width="1px" android:color="#444" />
<corners android:radius="18dp" />
<gradient android:startColor="#3787ff" android:endColor="#2f72d7" android:angle="270" />
<corners android:radius="18dp" />
</shape>
</item>

<!-- default -->
<item>
<shape>
<solid android:color="#fff"/>
<stroke android:width="1px" android:color="#444" />
<corners android:radius="18dp" />
</shape>
</item>
</selector>
Yukarıdaki gibi her birini item etiketlerinin altına yazabildiğimiz gibi, bu durumları ayrı xml dosyalarına bölüp item etiketine ilgili durumun xml dosyasınıda verebiliriz. Tıpkı aşağıdaki gibi:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<!-- pressed -->
<item android:state_pressed="true" android:drawable="@drawable/cust_btn_pressed_state"/>

<!-- focused -->
<item android:state_focused="true" >
<shape>
<stroke android:width="1px" android:color="#444" />
<corners android:radius="18dp" />
<gradient android:startColor="#3787ff" android:endColor="#2f72d7" android:angle="270" />
<corners android:radius="18dp" />
</shape>
</item>

<!-- default -->
<item>
<shape>
<!-- Opak olarak beyaz (#fff) arka plan -->
<solid android:color="#fff"/>
<!-- Kenarlık diye 1px #ff007f renginde(stroke) -->
<stroke android:width="1px" android:color="#ff007f" />
<!-- Köşeler 18dp çapında yuvarlansın -->
<corners android:radius="18dp" />
</shape>
</item>

</selector>
Pressed halini drawable klasöründe cust_btn_pressed_state.xml dosyasına yazıyor ve item etiketinede android:drawable="@drawable/cust_btn_pressed_state" xml özelliği içinde belirtiyoruz.
Peki cust_btn_pressed.xml dosyamız nasıl oldu:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Artık state_pressed olduğunu buraya yazmamıza gerek yok. Çünkü bir üst xmlden bu xml i çağırıyoruz ve orada state_pressed olarak belirtildi. -->
<item>
<shape>
<stroke android:width="1px" android:color="#444" />
<corners android:radius="18dp" />
<gradient android:startColor="#3787ff" android:endColor="#2f72d7" android:angle="270" />
<corners android:radius="18dp" />
</shape>
</item>

</selector>

android:text


Düğmemizin üstüneki yazıya renk, gölge, ebat, tarz(stil) eklemek için kullandığımız xml özelliklerini(attribute) her düğmeye bu özellikleri tekrar tekrar yazmamak için tarz(style) dosyası oluşturmamız gerek. styles.xml dosyasına uygulamamızın css dosyası gibi bakabiliriz. Burada bir css elementi oluşturur style etiketi içine tarz bilgilerini yazalım.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="cust_btn_stil">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#ffffff</item>
<item name="android:gravity">center</item>
<item name="android:layout_margin">3dp</item>
<item name="android:padding">10dp</item>
<item name="android:textSize">20dp</item>
<item name="android:textStyle">normal</item>
<item name="android:shadowColor">#e2e</item>
<item name="android:shadowDx">1</item>
<item name="android:shadowDy">1</item>
<item name="android:shadowRadius">2</item>
</style>
</resources>
Artık düğmemize(button) şu xml özelliğini(xml attribute) ekleyerek düğmemizin üstündeki metnin tarzını hızlıca atamış oluruz. Dahası bundan sonra aynı tarzda olacak elemanlarada kısaca bu bilgiyi atayabiliriz.
<Button
android:id="@+id/btnNext"
android:text="@string/btnNext"
android:background="@drawable/cust_btn_bg"
style="@style/cust_btn_tarz" />


android:textColor


cust_btn_text.xml adlı dosyayı res/drawable klasöründe saklayalım.Text özelliklerini biraz değiştirerek yukarıdaki styles.xml dosyasında sakladık ama düğmeye basıldığında metin rengi değişik olsun istiyoruz. Bunu sağlamak için cust_btn_text.xml dosyasını aşağıdaki gibi düzenleyelim:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- pressed -->
<item android:state_pressed="true" android:color="#ffff00" />

<!-- focused -->
<item android:state_focused="true" android:color="#fff" />

<!-- default -->
<item android:color="#385487" />

</selector>
Artık düğmemizin metin rengide her durumda farklı bir renk alacak. Bu kaynak dosyasını(resource file hatta drawable file) düğmemizin belirtildiği(declare edildiği) xml etiketinde android:textColor xml özelliğinde belirtelim. Artık düğmemizin son hali:
<Button
android:id="@+id/btnNext"
android:text="@string/btnNext"
android:background="@drawable/cust_btn_bg"
style="@style/cust_btn_tarz"
android:textColor="@drawable/cust_btn_text" />
olacak.

Bu kadar yeterli sanırım bu işi anlamak için. Sonuçta çıkan düğmenin renkleri başta belirttiğimiz gibi olmadı çünkü bende öğrenirken oynaya oynaya yoldan çıkarttım düğmemizi :)



Referanslar: Drawable Resources(developer.android.com)
Bitmap File
A bitmap graphic file (.png, .jpg, or .gif). Creates a BitmapDrawable.
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/myimage" />

Nine-Patch File
A PNG file with stretchable regions to allow image resizing based on content (.9.png). Creates a NinePatchDrawable.
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/myninepatch" />

Layer List
A Drawable that manages an array of other Drawables. These are drawn in array order, so the element with the largest index is be drawn on top. Creates a LayerDrawable.
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:id="@[+][package:]id/resource_name"
android:top="dimension"
android:right="dimension"
android:bottom="dimension"
android:left="dimension" />
</layer-list>

State List
An XML file that references different bitmap graphics for different states (for example, to use a different image when a button is pressed). Creates a StateListDrawable.
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize=["true" | "false"]
android:dither=["true" | "false"]
android:variablePadding=["true" | "false"] >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_window_focused=["true" | "false"] />
</selector>

Level List
An XML file that defines a drawable that manages a number of alternate Drawables, each assigned a maximum numerical value. Creates a LevelListDrawable.
<level-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@drawable/drawable_resource"
android:maxLevel="integer"
android:minLevel="integer" />
</level-list>

Transition Drawable
An XML file that defines a drawable that can cross-fade between two drawable resources. Creates a TransitionDrawable.
<transition
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:id="@[+][package:]id/resource_name"
android:top="dimension"
android:right="dimension"
android:bottom="dimension"
android:left="dimension" />
</transition>

Inset Drawable
An XML file that defines a drawable that insets another drawable by a specified distance. This is useful when a View needs a background drawble that is smaller than the View's actual bounds.
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/drawable_resource"
android:insetTop="dimension"
android:insetRight="dimension"
android:insetBottom="dimension"
android:insetLeft="dimension" />

Clip Drawable
An XML file that defines a drawable that clips another Drawable based on this Drawable's current level value. Creates a ClipDrawable.
<clip
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/drawable_resource"
android:clipOrientation=["horizontal" | "vertical"]
android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal" | "fill_horizontal" |
"center" | "fill" | "clip_vertical" | "clip_horizontal"] />

Scale Drawable
An XML file that defines a drawable that changes the size of another Drawable based on its current level value. Creates a ScaleDrawable
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/drawable_resource"
android:scaleGravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal" | "fill_horizontal" |
"center" | "fill" | "clip_vertical" | "clip_horizontal"]
android:scaleHeight="percentage"
android:scaleWidth="percentage" />

Shape Drawable
An XML file that defines a geometric shape, including colors and gradients. Creates a ShapeDrawable.
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape=["rectangle" | "oval" | "line" | "ring"] >
<corners
android:radius="integer"
android:topLeftRadius="integer"
android:topRightRadius="integer"
android:bottomLeftRadius="integer"
android:bottomRightRadius="integer" />
<gradient
android:angle="integer"
android:centerX="integer"
android:centerY="integer"
android:centerColor="integer"
android:endColor="color"
android:gradientRadius="integer"
android:startColor="color"
android:type=["linear" | "radial" | "sweep"]
android:usesLevel=["true" | "false"] />
<padding
android:left="integer"
android:top="integer"
android:right="integer"
android:bottom="integer" />
<size
android:width="integer"
android:height="integer" />
<solid
android:color="color" />
<stroke
android:width="integer"
android:color="color"
android:dashWidth="integer"
android:dashGap="integer" />
</shape>