Repeated Bitmap not working (stretched) on Android 2.3 (Gingerbread)

Problem

Jadi kejadiannya adalah saat saya membuat pattern untuk background image aplikasi dengan cara kayak gini (background.xml):

<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/bg_pattern"
    android:tileMode="repeat" />

dimana bg_pattern ini image png yang ingin di repeat buat jadi background screen. kemudian saya set background ini di layout fragment yang saya gunakan kurang lebih kayak gini:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background">

    <!--Views banyak di sini-->

</FrameLayout>

it work great di device dengan Android OS versi 3 (Honeycomb) dan yang lebih baru, tapi masalah muncul saat saya test di device dengan OS versi 2.3 (saat test dengan galaxy ace, OS 2.3), gambar background bukannya di repeat malah ke stretch. Setelah googling sebentar, ternyata ini memang bugs di android OS.

Solution

Untungnya, ada workaround untuk kasus kayak gini, caranya adalah selalu mem-force repeat background di program. jadi, saya membuat sebuah static function di kelas statis saya (ie. AndroidUtils):

/***
	 * fix stretched image (bug on android  < 3)
	 * @param view view within which background image doesn't repeat correctly (stretched)
	 */
	public static void fixBackgroundRepeat(View view) {
	    Drawable bg = view.getBackground();
	    if (bg != null) {
	        if (bg instanceof BitmapDrawable) {
	            BitmapDrawable bmp = (BitmapDrawable) bg;
	            bmp.mutate(); // make sure that we aren't sharing state anymore
	            bmp.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
	        }
	    }
	}

dan di setiap fragment dengan background repeated bitmap, saat create view-nya saya memanggil fungsi tersebut:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.fragment_layout, container, false);

		// make sure, background image repeated properly
		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB){
			AndroidUtils.fixBackgroundRepeat(view);
		}
		return view;
	}

sejauh ini cara ini bisa menyelesaikan masalah yang saya temui.
jika punya cara lain, silahkan di share di comment :)

happy coding.

daftar cara yang mungkin bisa di coba:

  1. Pastiin image pattern berukuran bilangan pangkat dua (misal. 16x16px, 32x32px, dst)

Detik app for Android possible improvement

disclaimer: investigasi ini merupakan inisiatif saya sendiri sebagai developer android dan tidak ada kaitannya dengan perusahaan tempat saya bekerja.

Salah satu cara meningkatkan performance aplikasi android kita adalah dengan menggunakan View seminimal mungkin. Dalam blog ini saya akan mencoba menginvestigasi salah satu aplikasi android lokal yang paling populer yaitu aplikasi Detik (saya masih penasaran kenapa mereka tidak menggunakan reverse domain untuk package name-nya, malah menggunakan org.detik ?). Karena dengan melihat sekilas kita bisa tahu, bahwa aplikasi ini masih bisa di improve lagi.

Kali ini saya ingin melihat struktur layout dari sliding menu dari aplikasi detik. Untuk melihat struktur layout aplikasi tanpa melakukan reverse engineer cukup mudah dengan menggunakan UI Automator:

  1. Jalankan aplikasi detik di smartphone dengan OS Honeycomb atau yang lebih baru dengan debug mode.
  2. gantri prespective eclipse ke DDMS
  3. Dump hierarchy vie hierarchy
  4. Screen Shot 2013-10-07 at 7.37.47 PMkita lihat hasilnya seperti ini Screen Shot 2013-10-07 at 7.41.05 PM

dari gambar no 4 di atas kita lihat, untuk mendefinisikan satu menu, developer aplikasi ini menggunakan struktur yang lumayan komplek kurang lebih seperti ini:

<LinearLayout>
	<ImageView />
	<TextView />
</LinearLayout>

sebenarnya struktur ini bisa lebih disederhanakan, caranya adalah dengan menggunakan compound drawable, cukup dengan menggunakan satu TextView dan leftDrawable kurang lebih seperti ini:


<TextView
 android:drawableLeft="@drawable/icon"
 background="@drawable/selector"/>

di sini menggunakan drawableLeft untuk setting icon static yang digunakan di setiap menu-nya, dan menggunakan background selector untuk memberikan background sesuai dengan state dari textview tersebut. Dengan cara ini, aplikasi tersebut bisa lebih efisien lagi, karena hierarki view yang lebih flat dan jumlah view yang jauh lebih sedikit.

mungkin teknik ini bisa anda gunakan untuk aplikasi yang sedang anda develop ;)

 

happy coding

Facebook for Android Application Startup issue

Jika anda pengguna aplikasi facebook di smartphone Android seperti saya, kemungkinan anda pernah melihat halaman hitam saat pertama kali anda menjalankan aplikasi tersebut.

 

Jika anda adalah developer android seperti saya, sebenarnya tidak sulit membuat aplikasi kita saat startup agar tidak menampilkan halaman hitam, tapi warna background dari aplikasi kita, caranya adalah:

1. buat theme untuk aplikasi yang kita buat di file style.xml, contoh

    <style name="Theme.AplikasiKeren" parent="android:style/Theme.Light">
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowBackground">@drawable/background_app</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:screenOrientation">portrait</item>
    </style>
    

yang perlu anda perhatikan adalah item dengan atribut name android:windowBackground, di sini kita bisa setting warna/bitmap dari window background saat sebuah halaman mulai ditampilkan.
2. jadikan theme ini sebagai theme dari aplikasi di file AndroidManifest.xml

 <application
        android:name="AplikasiKeren"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:logo="@drawable/ic_launcher"
        android:theme="@style/Theme.AplikasiKeren" >
....
</application>

dengan begini, saat aplikasi anda mulai berjalan, background window yang akan di tampilkan adalah sesuai dengan background yang sudah anda setting di theme pada langkah pertama tersebut. gampang, kan :)

happy coding.