11 Temmuz 2014 Cuma

Android DatePickerDialog'daki DayPicker'i Gizleme


Merhabalar,

Android'de ekranda fazla yer kaplamadan kullanıcıdan tarih bilgisi almanın yolu, içerisinde tarih seçicisi bulunduran DatePickerDialog'dan geçer. Bu dialog tipi içerisinde DatePicker komponentini barındırarak gün, ay ve yıl spinner'larıyla tarih seçme işlemini kolaylaştırır.

Bazen bir iş kuralı gereği ("MMyyy" formatlı tarih bazlı raporlama gibi) bu üç kontrolden bazılarını gizlemek isteyebilirsiniz. Fakat bu kontrollerin erişimi dışa kapalı olduğu için ilgili sınıflar üzerinde işinize yarayacak methodlar yok. E o zaman bu küçük ister için kendi DatePicker'ımızı mı yazacağız? Tabii ki hayır! Bu noktada reflection'ın nimetlerinden yararlanarak küçük bir çakallıkla durumun üstesinden geleceğiz: DatePickerDialog sınıfı aslında içerisinde bir adet DatePicker barındırıyor, DatePicker da üç adet NumberPicker. Encapsulation gereği bu üç NumberPicker'a dışardan erişim kapalı. Bu durumda biz de reflection'ı kullanarak ilgili kontrollere erişip amacımıza ulaşacağız.

Bu doğrultuda gün seçicisini gizlemek istiyor olalım. O zaman DatePicker sınıfının kaynak koduna bakıp ilgili üye değişkeni bulmamız yeterli. Aradığımız tanımlama 93. satırda:

private final NumberPicker mDaySpinner;


Evet artık işimiz çok kolay, görüldüğü üzere gün seçiçimiz NumberPicker tipinden dolayısıyla setVisibility() metodunu kullanarak bu kontrolü gizleyebileceğimiz aşikar. Aşağıdaki kod parçasında olduğu gibi picker'a ulaşıp gizliyoruz:
  public void openDatePickerDialog(View view) throws IllegalAccessException {
        DatePickerDialog dialog = new DatePickerDialog(this, null, 2014, 1, 1);
        
        // honeycomb(api level 11) ve üzeri android versiyonlu tabletlerde çıkan takvim tablosunu gizle
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            dialog.getDatePicker().setCalendarViewShown(false);
        }
        
        // DatePicker sınıfının üye degiskenlerini al
        Field[] fields = DatePicker.class.getDeclaredFields();
        for (Field field : fields) {
            // ilgilendiğimiz üye değişken mi?
            if (field.getName().equalsIgnoreCase("mDayPicker")  // honeycomb alti
                || field.getName().equalsIgnoreCase("mDaySpinner") // honeycomb ve ustu
            ) {
                field.setAccessible(true);
                Object dayPicker = field.get(dialog.getDatePicker());
                ((View) dayPicker).setVisibility(View.GONE);
            }
        }

        dialog.show();
    }
Hement test edelim, ekran çıktısı:

DaySpinner'ı gizlemiş olsak da gün bilgisinin halen dialog'un başlık kısmında yer alması hoş değil, DatePicker'ın change event'ında bu problemi gideriyoruz:
   // dialog.title'da gün bilgisi gösterimini engelleme
 // DatePicker tipinin  OnDateChangedListener eventini ancak initialization sırasında set edebiliyoruz
 dialog.setTitle("choose date");
 dialog.getDatePicker().init(2014, 1, 1, new DatePicker.OnDateChangedListener() {
     @Override
     public void onDateChanged(DatePicker datePicker, int i, int i2, int i3) {
        dialog.setTitle("choose date");
     }
 });

Kodların tamamına burdan ulaşabilirsiniz.

Bu tarz küçük/pratik çözümler bazen çok faydalı olabiliyor, umarım sizin de işinie yarar, hayırlı ramazanlar.

Hiç yorum yok:

Yorum Gönder