Son zamanlarda bir uygulama için tanımladığınız davranışın aynısını uygulamak zorunda kaldık. Uygulamanın ekranları ve genel akışı zaten tanımlanmıştı, bu yüzden buna bağlı kalmalıydık (bir iOS uygulama klonu ...). Neyse ki, ekran arka düğmelerinden kurtulmayı başardık :)
TabActivity, FragmentActivities (fragmanlar için destek kitaplığını kullanıyorduk) ve Fragment karışımını kullanarak çözümü hackledik. Geçmişe baktığımda, bunun en iyi mimari karar olmadığından eminim, ama işin işe yaramasını sağladık. Tekrar yapmak zorunda kalsaydım, muhtemelen daha fazla aktivite tabanlı bir çözüm yapmaya çalışabilirdim (fragman yok), ya da sekmeler için sadece bir Aktivitem var ve geri kalanların görünümler olmasına izin verdim (ki çok daha fazlasını buluyorum) genel faaliyetlerden daha fazla kullanılabilir).
Bu nedenle gereksinimler, her sekmede bazı sekmeler ve değiştirilebilir ekranlar olmasıydı:
tab 1
screen 1 -> screen 2 -> screen 3
tab 2
screen 4
tab 3
screen 5 -> 6
vb...
Diyelim ki: kullanıcı sekme 1'de başlar, ekran 1'den ekran 2'ye ve sonra ekran 3'e gider, daha sonra sekme 3'e geçer ve ekran 4'ten 6'ya gider; sekme 1'e geri dönülürse, ekran 3'ü tekrar görmeli ve Geri düğmesine basarsa ekran 2'ye dönmelidir; Tekrar geri döndüğünde ekran 1'de; sekme 3'e geçin ve tekrar ekran 6'da.
Uygulamadaki ana faaliyet TabActivity'yi genişleten MainTabActivity'dir. Her sekme bir etkinlikle ilişkilidir, diyelim ActivityInTab1, 2 ve 3. Ve sonra her ekran bir parça olacak:
MainTabActivity
ActivityInTab1
Fragment1 -> Fragment2 -> Fragment3
ActivityInTab2
Fragment4
ActivityInTab3
Fragment5 -> Fragment6
Her ActivityInTab her seferinde sadece bir parça tutar ve bir parçayı diğeri için nasıl değiştireceğini bilir (hemen hemen bir ActvityGroup ile aynıdır). Harika olan şey, her sekme için ayrı sırt yığınlarını bu şekilde korumak oldukça kolaydır.
Her ActivityInTab için işlevsellik oldukça aynıydı: bir parçadan diğerine nasıl gidileceğini ve bir arka yığını nasıl koruyacağını biliyorsunuz, bu yüzden bunu bir temel sınıfa yerleştirdik. Basitçe ActivityInTab diyelim:
abstract class ActivityInTab extends FragmentActivity { // FragmentActivity is just Activity for the support library.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_in_tab);
}
/**
* Navigates to a new fragment, which is added in the fragment container
* view.
*
* @param newFragment
*/
protected void navigateTo(Fragment newFragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content, newFragment);
// Add this transaction to the back stack, so when the user presses back,
// it rollbacks.
ft.addToBackStack(null);
ft.commit();
}
}
Activity_in_tab.xml sadece şudur:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:isScrollContainer="true">
</RelativeLayout>
Gördüğünüz gibi, her sekmenin görünüm düzeni aynıydı. Çünkü her parçayı tutacak içerik adı verilen bir FrameLayout. Parçalar, her ekranın görüntüsüne sahip olanlardır.
Sadece bonus puanları için, kullanıcı Geri düğmesine bastığında ve geri dönecek daha fazla parça olmadığında onaylama iletişim kutusunu göstermek için küçük bir kod da ekledik:
// In ActivityInTab.java...
@Override
public void onBackPressed() {
FragmentManager manager = getSupportFragmentManager();
if (manager.getBackStackEntryCount() > 0) {
// If there are back-stack entries, leave the FragmentActivity
// implementation take care of them.
super.onBackPressed();
} else {
// Otherwise, ask user if he wants to leave :)
showExitDialog();
}
}
Bu hemen hemen kurulum. Gördüğünüz gibi, her bir FragmentActivity (ya da sadece Android> 3'teki Etkinlik) kendi FragmentManager'ı ile tüm geri istifleme ile ilgileniyor.
ActivityInTab1 gibi bir etkinlik gerçekten basit olacak, sadece ilk parçasını (yani ekran) gösterecek:
public class ActivityInTab1 extends ActivityInTab {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
navigateTo(new Fragment1());
}
}
Daha sonra, bir parçanın başka bir parçaya gitmesi gerekiyorsa, biraz kötü bir döküm yapması gerekir ... ama o kadar da kötü değil:
// In Fragment1.java for example...
// Need to navigate to Fragment2.
((ActivityIntab) getActivity()).navigateTo(new Fragment2());
Yani bu kadar. Bunun çok kanonik (ve çoğunlukla emin değilim çok iyi değil) bir çözüm olmadığından eminim, bu yüzden deneyimli Android geliştiricilerine bu işlevselliği elde etmek için daha iyi bir yaklaşımın ne olacağını sormak istiyorum. Android'de, beni açıklayan bir bağlantıya veya malzemeye yönlendirebilirseniz sevinirim . bu (sekmeler, sekmelerde iç içe ekranlar, vb) yaklaşmak için Android yolu. Yorumlarda bu cevabı koparmaktan çekinmeyin :)
Bu çözümün çok iyi olmadığının bir işareti olarak, son zamanlarda uygulamaya bazı navigasyon işlevleri eklemek zorunda kaldım. Kullanıcıyı bir sekmeden diğerine ve iç içe bir ekrana götürmesi gereken bazı tuhaf düğmeler. Bunu programlı olarak yapmak, kimin kimin problemleri olduğunu ve ne zaman uğraştığı parçaları ve aktiviteleri gerçekten somutlaştırıldıklarından ve başlattıklarından dolayı popoda bir acıydı. Bu ekranlar ve sekmeler gerçekten sadece Views gerçekten olsaydı çok daha kolay olurdu düşünüyorum.
Son olarak, yön değişikliklerinde hayatta kalmanız gerekiyorsa, parçalarınızın setArguments / getArguments kullanılarak oluşturulması önemlidir. Parçalarınızın yapıcılarında örnek değişkenleri ayarlarsanız vidalanırsınız. Ancak neyse ki düzeltmek gerçekten kolay: Yapımcıdaki setArguments içindeki her şeyi kaydedin ve sonra bunları kullanmak için onCreate'de getArguments ile bu şeyleri alın.