7.1 - Fragment nedir, nasıl kullanılır?
https://www.tutorialspoint.com/android/android_fragments.htm
A
Fragment is a piece of an activity which enable more modular activity design. ( Fragment, activity'nin bir parçasıdır, kendine ait
UIi'ı ve behaviour'ı vardır. Fragment'lar sayesinde daha modular activity
design'ları yapabiliriz, örneğin yazdığımız bir fragment'ı birden fazla
activity'de kullanabiliriz. )
It
will not be wrong if we say, a fragment is a kind of sub-activity. (Fragment'ı activity'nin bir parçası gibi düşünebiliriz
farzı misal bir fragment'a subactivity diyebiliriz. )
Fragment'lar hakkındaki bazı önemli notlar şunlardır :
- A
fragment has its own layout and its own behaviour with its own life cycle
callbacks.( Bir fragment kendi layout'una yani
kendi ui'ına sahiptir ve kendine ait bir davranışı vardır, kendine ait
lifecycle'ı vardır. )
-
You can add or remove fragments in an activity while the activity is running.( Bir activity çalışmaktayken bu activity'ye fragment
eklemek/silmek mümkündür. Yani runtime'da bir activity'ye fragment
eklenebilir/silinebilir. )
-
You can combine multiple fragments in a single activity to build a multi-plane
UI.( Bir activity, birden fazla fragment
içerebilir, yani bir ekranda farklı fonksiyonları ve farklı ui'ları olan birden
fazla birim(fragment) olabilir. )
- A
fragment can be used in multiple activities.( Bir
fragment, birden fazla activity'de kullanılabilir. )
-
Fragment life cycle is closely related to the life cycle of its host activity
which means when the activity is paused, all the fragments available in the
activity will also be stopped. ( Bir fragment'ın
lifecycle'ı, host activity'sinin(yani içerisinde olduğu activity'nin
lifecycle'ı) ile yakından ilişkilidir. Örneğin bir activity pause edildiğinde,
bu activity'nin içerdiği fragment'lar da pause edilir. )
- A
fragment can implement a behaviour that has no user interface component.( Bir fragment'da UI implement edilmeyip sadece behaviour
implement edilmesi mümkündür. )
-
Fragments were added to the Android API in Honeycomb version of Android which
API version 11.
You can create custom fragments by
extending Fragment class and You can insert a fragment into your activity
layout by declaring the fragment in the activity's layout file, as a <fragment>
element. ( Custom
bir fragment nasıl yaratabiliriz?
- Fragment class'ını extend eden bir class tanımlarız.
- Fragment class'ının gerekli lifecycle method'larını override
ederiz.
- Bir Activity'nin layout dosyasına <fragment> element'i
kullanarak, bu fragment'ı activity'ye insert ederiz. )
Prior to fragment introduction, we had a
limitation because we can show only a single activity on the screen at one
given point in time. So we were not able to divide device screen and control different parts separately. But with
the introduction of fragment we got more flexibility and removed the limitation
of having a single activity on the screen at a time. (
Fragment'ları bilmiyoruz diyelim, bu durumda ekranda sadece single bir activity
gösterebilirdik, ekranı ikiye ve üçe bölüp bu parçaları ayrı ayrı kontrol
edebilme şansımız olmazdı. Allah'a şükür fragment'lar var ki onların sayesinde
bir activity kendilerine ait fonksiyonları ve UI'ları olan
subactivity(fragment)'lardan oluşur. Veya bir fragment tanımlayıp birden fazla
activity'de tanımladığımız fragment'ı kullanabiliriz. )
Now we can have a single activity but
each activity can comprise of multiple fragments which will have their own
layout, events and complete life cycle. ( Single bir activity, birden fazla
fragment'dan oluşabilir. Herbir fragment'ın kendi layout'u, kendi event'i,
kendi life cycle'ı vardır. )
Örnek :
Following is a typical example of how
two UI modules defined by fragments can be combined into one activity for a
tablet design, but separated for a handset design.
The application can embed two fragments
in Activity A, when running on a tablet-sized device. However, on a
handset-sized screen, there's not enough room for both fragments, so Activity A
includes only the fragment for the list of articles, and when the user selects
an article, it starts Activity B, which includes the second fragment to read
the article. (Aşağıdaki
örneği inceleyelim. Soldaki resimde bir tablet sağdaki resimde ise bir telefon
vardır.
Bu uygulamayı
tablette açtığımızda, tablet ekranı daha büyük olduğu için, single bir
activity'de 2 fragment göstereceğiz.
Bu uygulamayı
telefonda açtığımızda ise, telefon ekranı daha küçük olduğu için, single bir
activity'de sadece 1 fragment göstereceğiz.
Soldaki resime
bakalım. Burada sadece bir tane activity vardır o da Activity A'dır. Bu
activity'ye Fragment A ve Fragment B insert edilmiştir. Soldaki liste Fragment
A'dır, sağdaki ise Fragment B'dir. Fragment A'daki listeden bir haber başlığı
seçilince Fragment B'de bu haberin içeriği gösterilir.
Sağdaki resime
bakalım. Burada 2 tane activity vardır :
Activity A ve Activity B . Activity A, sadece Fragment A'yı içerir. Activity B,
sadece Fragment B'yi içerir. Dolayısıyla telefon ekranında Fragment A'daki yani
Activity A'daki listeden bir haber başlığı seçilince, haberin detayını gösteren
Activity B sayfası açılır. )
Fragment Life
Cycle
Android fragments have their own life
cycle very similar to an android activity. This section briefs different stages
of its life cycle. ( Fragment'ların da
activity'lerin yaşam döngüsüne benzeyen bir yaşam döngüleri vardır. Bu konuda
fragment'ların yaşam döngülerindeki aşamaları öğreneceğiz. )
Here is the list of methods which you
can to override in your fragment class.( Fragment
class'ını extend bir class tanımlamıştık. Bu class'da Fragment class'ının şu
method'larını override edebiliriz. )
onAttach() : The fragment instance is
associated with an activity instance. The fragment and the activity is not
fully initialized yet. Typically you get in this method a reference to the
activity which uses the fragment for further initialization work. ( Bir fragment object, bir activity ile
ilişkilendirilirken örneğin fragment activity'ye insert edilirken bu method
çağırılır. Fragment ve activity henüz başlatılmamıştır. )
onCreate() : The system calls this
method when creating the fragment. You should initialize essential components
of the fragment that you want to retain when the fragment is paused or stopped,
then resumed.( Fragment yaratılırken sistem
otomatik olarak onCreate() method'unu çağırır. Fragment pause,stop edilirken ve
sonra resume edilirken, Fragment'ın tutmak,saklamak istediğimiz önemli
bileşenlerini onCreate() method'unun implementation'ında initialize etmeliyiz. )
onCreateView() : The system calls this
callback when it's time for the fragment to draw its user interface for the
first time. To draw a UI for your fragment, you must return a View component
from this method that is the root of your fragment's layout. You can return
null if the fragment does not provide a UI. (
Fragment, kendi UI'ını ilk defa çizeceği zaman onCreateView() callback fonksiyonu çağırılır otomatik olarak. Eğer
fragment'ın UI'ının ekranda çizilmesini (ve sonraki method'lar çağırıldığında bu
UI'ın görünebilir olmasını) istiyorsanız onCreateView() callback fonksiyonunu bir View component return
etmelidir, yani bu method'u implement edip bir View component return etmeliyiz.
Eğer fragment'ın UI'ı yoksa, sadece behaviour'ı varsa, onCreateView() method'unda null return etmeliyiz. )
onActivityCreated()
: onActivityCreated()
is called after the onCreateView() method when the host activity is created. Activity
and fragment instance have been created as well as the view hierarchy of the
activity. At this point, view can be accessed with the findViewById() method.
example. In this method you can instantiate objects which require a Context
object. ( onCreateView() method'u çağırılıp
fragment'ın UI'ı çizildikten sonra,bu fragment'ı içeren activity(host activity)
yaratılırken onActivityCreated() method'u çağırılır. onActivityCreated()
callback fonksiyonu çağırıldıktan sonra,
artık activity ve fragment yaratılmıştır, activity'nin view hiyerarşisi de
yaratılmıştır. Bu noktada findViewById() method'u çağırılarak bu view'e
erişilebilir. Ayrıca bu method'un implementation'ında, Context object gereken
object'leri instantiate edebilirsiniz??? )
onStart() : The onStart() method is
called once the fragment gets visible. ( Fragment'ın
görünür olması için onStart() callback fonksiyonu çağırılır. Yani onStart()
çağırıldıktan sonra fragment ekranda görünür olur artık. )
onResume() : Fragment becomes active.( onResume() çağırılınca Fragment ekranda aktif olur,
yani focus bu fragment'dadır, bir input girsek bu fragment'ı etkiler. )
onPause() : The system calls this
method as the first indication that the user is leaving the fragment. This is
usually where you should commit any changes that should be persisted beyond the
current user session. ( Fragment veya host activity
ekranda yarı görünür olduğunda, onPause() method çağırılır. Kullanıcının
uygulamadan ayrılmak üzere olduğunun ilk belirtisi bu method'un çağırılmasıdır,
kaybetmek istemediğimiz verileri bu method çağırıldığında kaydetmeliyiz ki
kullanıcı bu uygulamayı tekrar açtığında bu veriler kaybolmasın. )
onStop() : Fragment going to be
stopped by calling onStop(). ( Fragment tamamen
durdurulduğunda yani ekranda tamamen görünmez olduğunda onStop() method'u
çağırılır. Fragment tamamen durdurulur. )
onDestroyView() : Fragment view will be destroyed
after this method is called. ( Bu method
çağırıldığında ekranda çizilmiş olan fragment view yok edilir. )
onDestroy() : called to do final clean up
of the fragment's state but Not guaranteed to be called by the Android
platform. ( onDestroy() method'u çağırılınca
fragment'dan arta kalan tüm atıklar vs. hepsi yok edilip, genel bir temizlik
yapılır. Android'in bu method'ı otomatik olarak çağıracağı kesin değildir.
Dolayısıyla bu method'un kesinkes çağırılmasını istiyorsak manual olarak
çağırmalıyız. )
How
to use Fragments?
İlk olarak
kaç tane fragment kullanmak istediğimize karar vermeliyiz. 3 tane fragment
kullanmak istiyoruz diyelim.
- Bu durumda Fragment class'ını extend eden 3 tane class
tanımlamalıyız, Fragment class yukarıda bahsedilen callback fonksiyonlarına
sahiptir, biz kendi tanımladığımız Fragment subclass'ında bu callback
fonksiyonlardan ihtiyacımız olanları override ederiz.
- Sonra herbir fragment için yani 3 tane layout dosyası(.xml)
oluşturmalıyız, bu dosyalar herbir fragment'ın UI'ını belirler.
- İstediğimiz activity'ye istediğimiz fragment'ı ekleyebiliriz
artık, activity'nin layout(.xml) dosyasında <fragment> element'ini
kullanarak.
Types
of Fragments
3 çeşit fragment
vardır :
1 - Single frame
fragments :
Single frame fragments are using for hand hold devices like mobiles, here we
can show only one fragment as a view.
2 - List fragments : fragments having special
list view is called as list fragment
3 - Fragments
transaction
: Using with fragment transaction. we can move one fragment to another
fragment.
Single
Frame Fragment
Single
frame fragment is designed for small screen devices such as hand hold
devices(mobiles) and it should be above android 3.0 version. ( Küçük ekranlı
cihazlar için, örneğin mobil telefonlar için Single frame fragment kullanılır. Android 3.0 ve üzerin versiyonlar
için geçerlidir. )
This example will explain you how to
create your own Fragments. Bu örnekte kendi fragment'larımızı
tanımlayacağız. 2 tane fragment tanımlayacağız. Cihaz portrait modda iken yani
dikey tutulurken bu fragment'lardan biri kullanılacak, landscape modda iken
yani yatay tutulurken bu fragment'lardan diğeri kullanılacak. Yani telefon
dikey ve yatay pozisyondayken farklı fragment'lar dolayısıyla farklı ui'lar
göstereceğiz.
-
MyFragments
isimli bir uygulama yaratalım. com.example.myfragments
package'ı altında boş bir activity yaratalım bunun adı MainActivity.java
olsun.
-
MainActivity class'ında cihazın orientation'ını check edelim, yani cihaz dik mi
yatay mı tutuluyor diye bakalım ve buna göre uygun fragment'laı kullanalım.
-
com.example.myfragments package'ı
altında Fragment class'ını extend eden PM_Fragment ve
LM_Fragment diye
2 tane class tanımlayalım. Bu class'larda Fragment class'ının gerekli lifecycle
callback fonksiyonlarını override edelim.
- res/layout/lm_fragment.xml ve
res/layout/pm_fragment.xml isimli 2 tane layout
dosyası oluşturalım. Bu dosyalar biraz önce tanımladığımız 2 farklı fragment'ın
layout'ları olarak kullanılacaktır. Soru: fragment class'ları ve fragment
layout dosyalarını tanımladıktan sonra bu ikisi arasındaki ilişkiyi nerede
kuruyoruz?
- Projeyi ilk oluşturduğumuzda otomatik
olarak yaratılmış olan res/layout/activity_main.xml dosyasını
açalım. Bu bizim main activity'mizdir yani uygulama açıldığında gösterilecek
olan activity'dir. Bu activity'nin layout dosyasına <fragment>
element'ini kullanarak fragment'ları koyalım.
- res/values/strings.xml dosyasında
gerekli string constant'ları tanımlayalım.
- Uygulamayı çalıştıralım. Ekran dikey
tutulduğunda ekranda gözüken activity'de res/layout/pm_fragment.xml
layout'u ile tanımlanan fragment kullanılır. Ekran yatay tutulduğunda ekranda
gözüken activity'de res/layout/lm_fragment.xml
layout'u ile tanımlanan fragment kullanılır.
Aşağıda şu dosyaları
tanımlayacağız :
- MainActivity.java - res/layout/activity_main.xml
- LM_Fragment.java - res/layout/lm_fragement.xml
- PM_Fragment.java - res/layout/pm_fragment.xml
MainActivity isimli class'ın onCreate()
method'unda, Configuration class'ından bir object nasıl elde ederiz? getResource().getConfiguration() method'unu
çağırarak. config object'in orientation isimli variable'ının değeri Configuration.ORIENTATION_LANDSCAPE mi
diye bakarız, öyleyse telefon yatay pozisyonda tutuluyordur.
getFragmentManager() method'unu
çağırarak FragmentManager object elde ederiz. fragmentManager object'in beginTransaction() method'unu
çağırarak fragmentTransaction object'i
elde ederiz.
fragmentTransaction
object'in replace()
method'u çağırılarak activity ile ilişkilendirilen fragment değiştirilir :
replace()
method'unun 2. parametresi activity ile ilişkilendirilecek olan fragment'ın
layout dosyasının ismidir.
replace() method'unun 1. parametresi olan android.R.id.content nedir? The
android.R.id.content
ID
value indicates the ViewGroup
of the entire content area of an Activity
. android.R.id.content gives you the root
element of a view. If you need root view of your activity (so you can add your
contents there) use findViewById(android.R.id.content). Bir Activity'nin tüm alanını kapsayan ViewGroup'un id'sidir
android.R.id.content. MainActivity class'ı içerisinde android.R.id.content
id'si, MainActivity layout'unun yani UI'ının root view'ine karşılık gelir. Yani
biz aslında replace method'unu çağırarak şunu yaparız. replace() method'unun 1.
parametresinde android.R.id.content
olduğu için ve 2.parametresinde ls_fragment olduğu için MainActivity'nin UI'ının tamamının yerine
ls_fragment object'in ilişkili olduğu layout olan lm_fragment.xml koyarız.
fragmentTransaction object ile işimiz bittikten sonra bu
object'in commit() method'unu çağırarak yapılan değişiklikleri kaydederiz.
Tanımladığımız Fragment subclass'larına bakalım. Bu
class'larda onCreateView() method'unu override ederiz, bu method'un ne return
ettiğine dikkat edelim. Bu fragment'ın view'ini yani layout'unu return
etmelidir onCreateView() method'u, bunu nasıl return etmişiz, inflater.inflate(R.layout.lm_fragment, container, false) method'unu çağırarak. onCreateView() method'u,
bu fragment'ın layout'ını yani UI'ını belirlemek için override edilir. Bu
fragment'ın layout'u lm_fragment.xml olarak
belirlenmiştir.
- activity_main layout'una 2 tane fragment element
eklenmiştir, tanımlanan her 2 fragment da eklenmiştir. Ancak MainActivity class'ında replace() method'u çağırılarak layout'un tümüne sadece 1 fragment layout
koyulmaktadır. O halde neden 2 tane fragment koyuldu main layout'a
activity_main.xml dosyasında? main layout'a fragment'lar static olarak
koyulduğu için bu fragment'lar runtime'da
activity'den çıkartılamaz diye okumuştum bir yerde burada neden böyle değil durum bu önemli soruyu cevapla!!! Cevap :
MainActivity'de hiçbir layout set edilmediğine dikkat et.
Yani bu örnekte activity_main. xml dosyası
kullanılmıyor. ) You cannot replace a fragment
defined statically in the layout file via a FragmentTransaction. You can
only replace fragments that you added dynamically.
src/com.example.mycontentprovider/MainActivity.java :
package com.example.myfragments;
import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.res.Configuration;
import android.view.WindowManager;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Configuration config = getResources().getConfiguration();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Device orientation'ını check et.
// Device dik mi yatay mı tutuluyor diye
bak.
if(config.orientation==Configuration.ORIENTATION_LANDSCAPE){
// Cihaz yatay tutuluyorsa bu kod block'u çalışır.
LM_Fragment ls_fragment = new LM_Fragment();
fragmentTransaction.replace(android.R.id.content, ls_fragment);
}
else
{
// Cihaz dik tutuluyorsa bu kod block'u çalışır.
PM_Fragment pm_fragment = new PM_Fragment();
fragmentTransaction.replace(android.R.id.content, pm_fragment);
}
fragmentTransaction.commit();
}
// end of onCreate() implementation
} // end of MainActivity class
implementation
LM_Fragment.java :
package com.example.myfragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class LM_Fragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
/**
* Inflate the layout for this fragment
*/
return inflater.inflate(R.layout.lm_fragment, container, false);
}
}
PM_Fragment.java :
package com.example.myfragments;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class PM_Fragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
/**
* Inflate the layout for this fragment
*/
return inflater.inflate(R.layout.pm_fragment, container, false);
}
}
res/layout/lm_fragment.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#7bae16">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/landscape_message"
android:textColor="#000000"
android:textSize="20px" />
<!-- More GUI components go here -->
</LinearLayout>
res/layout/pm_fragment.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#666666">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/portrait_message"
android:textColor="#000000"
android:textSize="20px" />
<!-- More GUI components go here -->
</LinearLayout>
res/layout/activity_main.xml :
(
activity_main
layout'unda root element olarak LinearLayout kullanılmıştır. Bu layout'un
altında 2 tane fragment element vardır. Bu fragment element'lerin id'leri,
fragment layout xml dosyalarının ismidir. )
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<fragment
android:name="com.example.fragments"
android:id="@+id/lm_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment
android:name="com.example.fragments"
android:id="@+id/pm_fragment"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
res/values/strings.xml :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MyFragments</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="landscape_message">This is Landscape mode fragment</string>
<string name="portrait_message">This is Portrait mode fragment></string>
</resources>
Uygulamamızı çalıştıralım.
Cihazı portrait modda tuttuğumuzda ekran
aşağıdaki gibi görünür. Yani activity'de portrait fragment kullanılır.
Cihazı landscape modda tuttuğumuzda
ekran aşağıdaki gibi görünür. Yani activity'de landscape fragment kullanılır.
Virtual
device'ımızın (Emulator'ın) orientation'ını değiştirmek için şu kısa yolları
kullanırız:
·
ctrl+F11 on Windows.
·
ctrl+F11 on Linux.
Bu örnekte kullanıcı cihazı dikey de
tutsa yatay da tutsa aynı activity gösterilir. Ancak yatay ve dikey tutulunca,
aynı activity içerisinde farklı ui ve farklı behaviour kullanılır ve
gösterilir, çünkü aynı activity içerisinde duruma göre ya portrait fragment
kullanılır ya da landscape fragment kullanılır. Örneğin dikey tutulurken yatay
tutulmaya başlanırsa, activity içerisinde kullanılan fragment değiştirilir.
Basic Communication
between two fragments ( 2 fragment birbiriyle nasıl iletişim kurar? )
http://stackoverflow.com/questions/13700798/basic-communication-between-two-fragments
Have a look at the Android deverlopers page: http://developer.android.com/training/basics/fragments/communicating.html#DefineInterface
Basically,
you define an interface in your Fragment A, and let your Activity implement
that Interface. Now you can call the interface method in your Fragment, and
your Activity will receive the event. Now in your activity, you can call your
second Fragment to update the textview with the received value. ( Fragment class'ını extend eden FragA ve FragB isimli bir class tanımlarız.
FragA class'ında bir inner interface(inner
class) tanımlarız. Activity class'ımız, bu interface'i yani FragmentA
class'ında tanımladığımız inner interface'i implement etmelidir. Bu örnekte FragA class'ında TextClicked isimli bir inner interface(inner
class) tanımlarız. Activity class'ımız, bu interface'i yani FragA class'ında tanımladığımız inner
interface'i, yani FragA. TextClicked isimli interface'i implement
etmelidir. FragA class'ında tanımladığımız TextClicked isimli inner interface'de sendText() isimli bir method declare ederiz,
activity class'ımızda sendText() method'unu implement ederiz. Özetle, FragA class'ında TextClicked isimli bir interface tanımlarız, bu
interface'de sendText() isimli bir method declare ederiz.
Activity class'ımızda ise TextClicked interface'ini dolayısıyla bu interface'deki sendText() method'unu implement ederiz.
FragA class'ının sahip olduğu TextClicked() interface'inin FragA class'ının ait olduğu activity'de
implement edilip edilmediğini nasıl kontrol edebiliriz, bunu nasıl check
edebiliriz. FragA class'ının onAttach() method'unda try-catch block'u içerisinde mCallback = (TextClicked) activity; satırını çağırırız.
Ayrıca
FragA class'ında, TextClicked isimli interface type'ında olan mCallback isimli bir reference variable tanımladık. Bu variable'ın onAttach() method'unda bir object'e refer etmesini sağladık : mCallback = (TextClicked) activity; Sonra bu variable'ı kullanarak TextClicked interface'inin sahip olduğu sendText() method'u çağırılır FragmentA class'ında.
Özetle,
FragA FragB'nin sahip olduğu bir method'u çağırmak istiyor, böylece FragB 'deki bir text'i güncellemek
istiyor. Bunun için FragmentA'da TextCLicked isimli bir interface declare edilir. FragmentA'yı içeren activity'de TextClicked isimli interface implement edilir. TexClicked isimli interface'in sahip olduğu
method olan sendText() method'u FragA'da çağırılır. sendText() method'unda FragmentManager elde
edilir, fragmentManager kullanılarak FragB elde edilir,sonra FragB class'ının updateText() method'u kullanılmaz. )
// You Activity implements your interface
public class YourActivity implements FragA.TextClicked{
@Override
public void sendText(String text){
// Get Fragment B
FraB frag = (FragB)getSupportFragmentManager(). findFragmentById(R.id.fragment_b);
frag.updateText(text);
}
}
// Fragment A defines an Interface, and calls the method when needed
public class FragA extends Fragment{
TextClicked mCallback;
public interface TextClicked{
public void sendText(String text);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented the callback interface. If not, it throws an exception.
try {
mCallback = (TextClicked) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement TextClicked");
}
}
public void someMethod(){
mCallback.sendText("YOUR TEXT");
}
@Override
public void onDetach() {
mCallback = null; // => avoid leaking, thanks @Deepscorn
super.onDetach();
}
}
// Fragment B has a public method to do something with the text
public class FragB extends Fragment{
public void updateText(String text){
// Here you have it
}
}
https://developer.android.com/guide/components/fragments.html
A Fragment represents a behavior or a
portion of user interface in an Activity. You can combine multiple fragments in
a single activity to build a multi-pane UI and reuse a fragment in multiple
activities. You can think of a fragment as a modular section of an activity,
which has its own lifecycle, receives its own input events, and which you can
add or remove while the activity is running (sort of like a "sub
activity" that you can reuse in different activities). ( Bir activity, birden fazla Fragment içerebilir. Bir
fragment birden fazla activity'de kullanılabilir. Fragment'ı, bir activity'nin
modular bir kısmı olarak düşünebiliriz, fragment'lar farklı activity'lerde
tekrar tekrar kullanılabilirler, modular ve tekrar kullanılabilir kod yazmamızı
sağlarlar. Fragment'ların kendilerine ait lifecycle'ları vardır. kendi
input'larını alırlar. Activity çalışırken activity'den bir fragment'ı
çıkarabiliriz veya activity'ye yeni bir fragment ekleyebiliriz. Fragment'ı bir
subactivity gibi düşün. Bir fragment'ı tanımladıktan sonra bu fragment'ı farklı
farklı activity'lerde kullanabiliriz. )
A fragment must always be embedded in an
activity and the fragment's lifecycle is
directly affected by the host activity's lifecycle. For example, when the
activity is paused, so are all fragments in it, and when the activity is
destroyed, so are all fragments.
However, while an activity is running (it
is in the resumed lifecycle state), you can manipulate each fragment
independently, such as add or remove them.
When you perform such a fragment
transaction, you can also add it to a back stack that's managed by the
activity—each back stack entry in the activity is a record of the fragment
transaction that occurred. The back stack allows the user to reverse a fragment
transaction (navigate backwards), by pressing the Back button.
( Her
Fragment mutlaka bir activity içerisinde gömülü olmak zorundadır. Bir
fragment'ın yaşam döngüsü host activity'nin(yani fragment'ı içeren, fragment'ın
ev sahibi olan, fragment'ı misafir eden activity'nin) yaşam döngüsünden
etkilenir. Örneğin, host activity pause state geçince, fragment da pause
state'e geçer; host activity destroy edilince(yok edilince), fragment da
destroy edilir.
Buna karşın, bir activity çalışırken yani
activity resumed state'de iken herbir fragment host activity'den bağımsız
hareket edebilir, her state'de olabilir, yeni bir fragment eklenebilir veya
varolan bir fragment çıkartılabilir.
Bir activity'den başka bir activity'ye
geçerken eski activity back stack'a konulur hatırlayalım, sonra geri tuşuna
basarsak bir önceki activity back stack'dan getirilirdi hatırlayalım. Bu işlem
otomatik olarak yapılır. Fragment'larda da backstack kavramı vardır, ancak bu işlem
otomatik olarak değil manual olarak yapılır. Bir fragment'dan başka bir
fragment'a geçerken eski fragment'ı back stack'a koyabiliriz. Sonra istediğimiz
zaman back stack'dan fragment'ı getirebiliriz. Bu backstack'ı activity yönetir.
Backstack sayesinde fragment transaction tersine işler yani geri tuşuna basan
kullanıcı önceki fragment'lara geri gelir.
)
When you add a fragment as a part of your
activity layout, it lives in a ViewGroup inside the activity's view hierarchy
and the fragment defines its own view layout. You can insert a fragment into
your activity layout by declaring the fragment in the activity's layout file,
as a <fragment> element, or from your application code by adding it to an
existing ViewGroup. However, a fragment is not required to be a part of the activity
layout; you may also use a fragment without its own UI as an invisible worker
for the activity.
( Bir
activity'ye bir fragment'ı static olarak nasıl ekleriz? activity'nin layout xml
dosyasında fragment element'ini kullanarak.
Bir activity'ye bir fragment'ı dynamic
olarak nasıl ekleriz? .java dosyasında varolan bir ViewGroup'a fragment'ı
ekleyerek.
Fragment'ın bir activity'nin UI'ının
parçası olması zorunluluğu yoktur. Bir fragment'ın UI layout'u olmayabilir,
sadece behaviour'ı olabilir.)
This document describes how to build your
application to use fragments, including how fragments can maintain their state
when added to the activity's back stack, share events with the activity and
other fragments in the activity, contribute to the activity's action bar, and
more. ( Bu dökümanda şunları öğreneceğiz :
-
Uygulamada fragment'ları nasıl kullanacağımızı.
-
Fragment'lar activity'nin back stack'ına eklendiğinde fragment'ların
state'lerini nasıl sürdürebileceklerini.
-
Fragment'ların activity ve fragment'larla nasıl iletişim kuracakları. )
Design
Philosophy
Android introduced fragments in Android
3.0 (API level 11), primarily to support more dynamic and flexible UI designs
on large screens, such as tablets. Because a tablet's screen is much larger
than that of a handset, there's more room to combine and interchange UI
components. Fragments allow such designs without the need for you to manage
complex changes to the view hierarchy. By dividing the layout of an activity
into fragments, you become able to modify the activity's appearance at runtime
and preserve those changes in a back stack that's managed by the activity. ( Android, Android 3.0 sürümüyle birlikte fragment'lar
geldi. Fragment'ların ortaya çıkış nedeni, tablet gibi daha büyük ekranlı
cihazlarda daha dinamik daha esnek UI dizaynları sağlamaktı. Telefon ekranına
sığmayan UI'ları tablet ekranında göstermek
rahatlıkla mümkündür. Fragment'lar sayesinde activty'nin layout'unu
fragment'lara böleriz, activity'nin görünümünü runtime'da değiştirebiliriz ve
bu değişiklikleri backstack'da saklayabiliriz. )
For example, a news application can use
one fragment to show a list of articles on the left and another fragment to
display an article on the right—both fragments appear in one activity, side by
side, and each
fragment has its own set of lifecycle callback methods and
handle their own user input events. Thus, instead of
using one activity to select an article and another activity to read the
article, the user can select an article and read it all within the same
activity, as illustrated in the tablet layout in figure 1. ( Örneğin bir haber uygulaması düşünelim. Ekranda solda
haber başlıklarının listesi gösteren bir fragment olsun. Ekranda sağda ise
seçilen haber başlığıyla ilgili haberin detayları gösterilsin. Bu iki fragment
aynı activity'de yan yana gösterilir ekranda. Herbir fragment, kendi yaşam
döngüsü callback method'larına sahiptir, ve kendi input event'lerini handle
ederler. Bu sayede, haber başlıklarını ve haber detaylarını ayrı activity'lerde
göstermek yerine bir ekranı ikiye böleriz, yani aynı activity içerisinde
kullanıcının ekranın solundan haber başlıklarını seçip ekranın solunda seçtiği
haberin detaylarını görür. )
You should design each fragment as a
modular and reusable activity component. That is, because each fragment defines its own layout
and its own behavior with its own lifecycle callbacks, you can include one
fragment in multiple activities, so you should design for reuse and
avoid directly manipulating one fragment from another fragment. This is
especially important because a modular fragment allows you to change your
fragment combinations for different screen sizes. When designing your
application to support both tablets and handsets, you can reuse your fragments
in different layout configurations to optimize the user experience based on the
available screen space. For example, on a handset, it might be necessary to
separate fragments to provide a single-pane UI when more than one cannot fit
within the same activity. ( Herbir fragment tekrar
kullanılabilir mobular bir activity bileşenidir. Dolayısıyla fragment'lar
birden fazla activity'de kulanılabilirler. Bu çok önemlidir çünkü modular
fragment bize farklı ekran size'ları için fragment'ları değiştirebilmemizi
sağlar. Uygulamanızın hem tablet'de hem
de telefonda çalışmasını istiyoruz diyelim, aşağıdaki 2 resme bakalım. Soldaki
resimde bir tablet sağdaki resimde bir telefon vardır. Tablet ekranında 1 tane
activity'de 2 tane fragment vardır, soldaki fragment'dan haber başlığı seçilir,
sağdaki fragment'da haberin detayı gösterilir. Telefonda ise haber başlıkları
ve haber detayları ayrı activity'lerdeki fragment'larda gösterilir, bir haber
başlığı seçilince başka bir activity açılır, bu activity'deki bir fragment'da
haberin detayları gösterilir. )
Figure 1. An example of how two UI
modules defined by fragments can be combined into one activity for a tablet
design, but separated for a handset design. ( Haber
uygulaması tablet'de ve telefonda farklı görünür. Tablet'de aynı activity'de
haber başlığı ve haber detayı fragment'ları yan yanadır. Telefonda ise haber
başlığı ve haber detayı fragment'ları farklı activity'ler içerisindedir. )
For example—to continue with the news
application example—the application can embed two fragments in Activity A, when
running on a tablet-sized device. ( News uygulaması
örneğiyle devam edelim. Tablet-size'ında bir cihazda, Activity A'da 2 tane
fragment gömülüdür. )
However, on a handset-sized screen,
there's not enough room for both fragments, so Activity A includes only the
fragment for the list of articles, and when the user selects an article, it
starts Activity B, which includes the second fragment to read the article. ( Telefonda ise Activity A haber başlıkları fragment'ını
içerir. Activity B haber detayları
fragment'ını içerir. )
Creating a
Fragment
Figure 2. The
lifecycle of a fragment (while its activity is running). ( Host activity çalışmaktayken, bir fragment'ın yaşam
döngüsü yukarıdaki diagram'daki gibi çalışır. )
To create a
fragment, you must create a subclass of Fragment (or an existing subclass of
it). The Fragment class has code that looks a lot like an Activity. It contains callback methods similar to an
activity, such as onCreate(), onStart(), onPause(), and onStop(). ( Bir fragment
yaratmak için Fragment class'ının veya bir Fragment subclass'ını extend eden
bir class tanımlarız. Fragment class'ının implementation'ı Activity class'ının
implementation'ına benzer. Fragment class'ı da Activity'nin içerdiği lifecycle
method'larına benzer lifecycle method'ları içerir. )
In fact, if
you're converting an existing Android application to use fragments, you might
simply move code from your activity's callback methods into the respective
callback methods of your fragment. (Varolan bir
uygulamayı fragment kullanacak bir hale dönüştürmek istiyorsak, activity'nin
callback method'larına karşılık gelen, fragment'daki callback method'larını
aynı şekilde implement ederiz. )
Usually, you
should implement at least the following lifecycle methods: (Fragment class'ının en azından şu method'larını override
etmeliyiz: )
onCreate()
The system
calls this when creating the fragment. Within your implementation, you should
initialize essential components of the fragment that you want to retain when
the fragment is paused or stopped, then resumed. (Sistem
fragment'ı yaratırken onCreate() method'unu çağırır. onCreate() method'unun
implementation'ındafragment'ın önemli bileşenlerini initialize etmeliyiz,
örneğin fragment pause veya stop edildikten sonra tekrar pause edildiğinde
fragment'ın sürdürmek istediğimiz bileşenlerini burada initialize ederiz. )
onCreateView()
The system calls this when it's time for
the fragment to draw its user interface for the first time. To draw a UI for
your fragment, you must return a View from this method that is the root of your
fragment's layout. You can return null if the fragment does not provide a UI. ( Fragment'ın bir ui'ı varsa yani ekranda görünmesini
istiyorsak bu method'u mutlaka implement etmeliyiz. Fragment, UI'ını ekranda
çizeceği zaman onCreateView()
method'u çağırılır. Bir fragment'ın ekranda bir UI'ının olmasını istiyorsak bu
method bir View return etmek zorundadır. Fragment'ın onCreateView() method'unda return edilen view fragment'ın layout'unun
root view'idir. )
onPause()
The system calls this method as the first
indication that the user is leaving the fragment (though it does not always
mean the fragment is being destroyed). This is usually where you should commit
any changes that should be persisted beyond the current user session (because
the user might not come back).( Fragment yarı
görünür olduğunda diğer bir deyişle kullanıcı fragment'dan çıkmak için ilk adım
attığında onPause() method çağırılır sistem
tarafından. onPause() method'undan sonra kullanıcı fragment'a geri dönebilir
veya uygulamayı terk edebilir. Current user session ile ilgili kaybetmek
istemediğimiz verileri onPause() method'unda kaydetmeliyiz, çünkü kullanıcının
uygulamayı terk etme ihtimali vardır. )
Most applications should implement at
least these three methods for every fragment, but there are several other
callback methods you should also use to handle various stages of the fragment
lifecycle. ( Çoğu
uygulamadaki tüm fragment'lar en az bu 3 method'u implement eder.
Fragment'ların başka yaşam döngüsü method'ları da vardır, gerek duyulan
lifecycle method'ları override edilebilir. )
There are also a few subclasses that you
might want to extend, instead of the base Fragment class: ( Base class olan Fragment'ı extend etmek yerine şu 3
Fragment subclass'larından birini extend etmek isteyebiliriz. )
DialogFragment
Displays a floating dialog. Using this
class to create a dialog is a good alternative to using the dialog helper
methods in the Activity class, because you can incorporate a fragment dialog
into the back stack of fragments managed by the activity, allowing the user to
return to a dismissed fragment.( Dialog yaratmak için
Activity class'ındaki dialog helper class'larını kullanmak yerine,
DialogFragment class'ını kullanmak iyi bir alternatiftir. Çünkü fragment'ları
backstack'a koyabiliriz bu sayede bir önceki dialog fragment'a dönebiliriz. )
Örnek
:
ListFragment
Displays a list of items that are managed
by an adapter (such as a SimpleCursorAdapter), similar to ListActivity. ( Bir adapter tarafından yönetilen item listesini
gösterir. )
It provides several methods for managing
a list view, such as the onListItemClick() callback to handle click events. ( Bir list view'i yönetmek için ListFragment class'ı
birkaç method sağlamıştır bize. Örneğin, onListItemClick() callback method'unu çağırarak listedeki item'lara
tıklanınca yapılacak işlemleri handle edebiliriz. )
PreferenceFragment
Displays a hierarchy of Preference
objects as a list, similar to PreferenceActivity. This is useful when creating
a "settings" activity for your application. (
Preference object'lerin hiyerarşisini bir liste halinde gösterir. PreferenceActivity'ye
benzer. Uygulamanız için bir ayarlar activity'si yaratmak için bu fragment
kullanılabilir. )
Adding a user
interface
A fragment is usually used as part of an
activity's user interface and contributes its own layout to the activity.( Genellikle bir fragment, bir activity'nin user
interface'inin bir kısmı olarak kullanılır ve kendisine ait layout'u activity
içerisine gömer. )
To provide a layout for a fragment, you
must implement the onCreateView()
callback method, which the Android system calls when it's time for the fragment
to draw its layout. ( Bir fragment için bir layout
belirlemek istiyorsak, onCreateView()
method'unu implement etmek zorundayız. Fragment,
layout'unu ekranda çizeceği zaman onCreateView()
method'u çağırılır. )
Your implementation of this method(onCreateView()) must return a View that is the root of your
fragment's layout. ( onCreateView() method'unun implementation'ı, fragment'ın layout'unun
root'u olan bir view return eder. )
Note: If your fragment is a subclass of
ListFragment, the default implementation returns a ListView from
onCreateView(), so you don't need to implement it. (
Eğer ListFragment'ı extend eden bir fragment tanımlıyorsak, onCreateView()
method'unu implement etmeye gerek yoktur. Çünkü ListFragment
class'ının sahip olduğu onCreateView() method'unun default implementation'ı zaten bir ListView implement
eder.)
To return a layout from onCreateView(),
you can inflate it from a layout resource defined in XML. To help you do so,
onCreateView() provides a LayoutInflater object. ( onCreateView()
method'unun bir UI layout'u return etmesini nasıl sağlarız? inflater.inflate() method'unu çağırarak. Bu method'a verdiğimiz ilk argument
fragment'ın layout xml dosyasıdır. onCreateView() method'unun 2. parametresini inflater.inflate()
method'una 2.argument olarak veririz. )
Örnek :
In the sample below, R.layout.example_fragment
is a reference to a layout resource named example_fragment.xml saved in the application
resources. For example, here's a subclass of Fragment that loads a layout from
the example_fragment.xml
file: ( Fragment class'ını extend eden bir class
tanımladık. Bu class'da onCreateView() method'unu implement ederiz. Fragment'ın
UI'ı example_fragment.xml dosyasında tanımlıdır, bu dosya ismini
inflater.inflate() method'una parametre olarak veririz. Artık bu fragment'ın
UI'ı example_fragment.xml 'de tanımlanan UI olmuştur. )
public static class ExampleFragment
extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment,
container, false);
}
}
The
container parameter passed to onCreateView() is the parent ViewGroup (from the
activity's layout) in which your fragment layout will be inserted. ( onCreateView() ve inflater.inflate() method'larının
aldığı 2.parameter olan container nedir? fragment'ın UI'ının insert edileceği
parent ViewGroup'dur(activity'dir gibi düşünebilirsin). Yani fragment'ın
view'i(UI'ının) container isimli ViewGroup'a konulur. )
The
savedInstanceState parameter is a Bundle that provides data about the previous
instance of the fragment, if the fragment is being resumed (restoring state is
discussed more in the section about Handling the Fragment Lifecycle). ( onCreateView() method'unun aldığı 3.parameter olan
savedInstanceState, bir Bundle'dır. fragment'ın önceki state'i ile ilgili bilgi
tutar. )
The
inflate() method takes three arguments:
1 -
The resource ID of the layout you want to inflate.
2 - The ViewGroup to be the parent
of the inflated layout. Passing the container is important in order for the
system to apply layout parameters to the root view of the inflated layout,
specified by the parent view in which it's going.
3 - A boolean indicating whether the
inflated layout should be attached to the ViewGroup (the second parameter)
during inflation. ( In this case, this is false because the system is already
inserting the inflated layout into the container—passing true would create a
redundant view group in the final layout. )
Now you've seen how to create a
fragment that provides a layout. Next, you need to add the fragment to your
activity. ( Bir Fragment'ın nasıl yaratıldığını
öğrendik. Şimdi ise bir fragment'ı activity'ye eklemeyi öğreneceğiz. )
Adding a fragment to
an activity
Usually,
a fragment contributes a portion of UI to the host activity, which is embedded
as a part of the activity's overall view hierarchy. There are two ways you can
add a fragment to the activity layout:
1 -
Declare the fragment inside the activity's layout file(activity'nin layout xml
dosyasında <fragment> element'ini kullanarak activity'ye bir fragment'ı
static olarak ekleriz. )
In this case, you can specify layout
properties for the fragment as if it were a view. The android:name attribute in
the <fragment> specifies the Fragment class to instantiate in the layout.
For example, here's the layout file for an activity with two fragments: (fragment'ın element'inin layout property'lerini de xml
dosyasında belirtiriz, yani fragment'ımız sanki bir view'miş gibi fragment'ın
property'lerini set edebiliriz. Aşağıdaki örnekte 2 tane fragment içeren bir
activity'nin layout xml dosyası gösterilmiştir. fragment element'inin
android:name attribute'ü ile fragment'ın hangi class'dan instantiate
edileceğini belirtiriz. )
<?xml version="1.0"
encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:name="com.example.news.ArticleListFragment"
android:id="@+id/list"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
<fragment
android:name="com.example.news.ArticleReaderFragment"
android:id="@+id/viewer"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
When
the system creates this activity layout, it instantiates each fragment
specified in the layout and calls the onCreateView() method for each one, to retrieve
each fragment's layout. ( Sistem bu activity'nin
UI'ını yaratırken, layout xml dosyasında belirtilen bu activity'nin içereceği 2
fragment'ı da instantiate eder, yaratılan 2 fragment object'in onCreateView()
method'larını çağırarak fragment'ların UI'larını elde eder. )
The
system inserts the View returned by the fragment directly in place of the
<fragment> element. ( fragment object'in
onCreateView() method'u otomatik olarak çağırılınca return edilen View,
activity'nin UI'ında fragment element'in olduğu yere yerleştirilir. )
Note:
Each fragment requires a unique identifier that the system can use to restore
the fragment if the activity is restarted (and which you can use to capture the
fragment to perform transactions, such as remove it). (
Herbir fragment unique bir identifier'a yani unique bir ID'ye sahiptir.
Activity restart edilirse, sistem bu id'yi kullanarak fragment'ı bulup restore
eder tekrar yükler. Ayrıca bu fragment'ı elde etmek için bu fragment'ın id'sine
ihtiyacınız vardır. )
There are three ways to
provide an ID for a fragment: (Bir fragment için unique id nasıl
belirleyebiliriz? Bunun 3 farklı yolu vardır. )
1 - Supply the android:id
attribute with a unique ID. (fragment element'in android:id attribute'üne unique
bir ID vererek. UI'lı bir fragment'ın id'sini android:id kullanarak
belirleyebiliriz. UI'sız bir fragment'ın id'sini belirlemek için android:id
kullanılamaz ) )
2 - Supply the android:tag attribute with a
unique string. (fragment element'in android:tag attribute'üne unique
bir string vererek fragment için unique bir id belirleyebiliriz. UI'sız ve UI'lı bir
fragment'ın id'sini android:tag kullanarak belirleyebiliriz. Ancak UI'sız bir
fragment'ın id'sini android:tag kullanarak belirlemek zorundayız. )
3 - If you provide neither of the
previous two, the system uses the ID of the container view. ( Eğer yukarıdaki 2 yoldan birini kullanarak bir
fragment'a manual olarak bir unique id sağlamazsa, sistem otomatik olarak
devreye girer ve fragment'ın id'sine container view'in ID'sini verir. )
2 -
Or, programmatically add the fragment to an existing ViewGroup. (
.java dosyasında bir fragment'ı bir activity'ye dinamik olarak eklemek.
Uygulama çalışmaktayken bir fragmant'ı activity'ye dinamik olarak ekleyebiliriz
veya çıkartabiliriz. )
At
any time while your activity is running, you can add fragments to your activity
layout. You simply need to specify a ViewGroup in which to place the fragment. (Activity çalışırken bir fragment'ı activity'ye
ekleyebiliriz veya çıkartabiliriz, yani dinamik olarak fragment ekleme çıkarma
yapabiliriz. Fragment'ı hangi ViewGroup'a(activity'ye de diyebiliriz)
ekleyeceğimizi belirtiriz.)
To make fragment transactions in your
activity (such as add, remove, or replace a fragment), you must use APIs from FragmentTransaction. (Activity'de fragment
transaction yapmak için yani activity'ye fragment eklemek veya activity'den bir
fragment'ı silmek veya bir fragment'ı replace etmek için FragmentTransaction class'ı kullanılır. )
You can get an instance of
FragmentTransaction from your Activity like this:( Activity class'ında getFragmentManager() method'unu çağırarak FragmentManager object elde ederiz. FragmentManager object'in beginTransaction() method'unu çağırarak FragmentTransaction object
elde ederiz. )
|
FragmentTransaction
fragmentTransaction = fragmentManager. beginTransaction();
You can
then add a fragment using the add() method, specifying the fragment to add and
the view in which to insert it. ( Elde ettiğimiz FragmentTransaction object'in add() method'unu çağırarak bir fragment'ı
activity'ye ekleyebiliriz. )
Örnek :
ExampleFragment fragment = new
ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
The first argument passed to add() is the ViewGroup in which the fragment
should be placed, specified by resource ID, and the second parameter is the
fragment to add. (
add() method'unun aldığı ilk parameter, fragment'ın hangi ViewGroup'a örneğin
hangi activity'ye ekleneceğini belirtir, bu parameter resource id'dir.
2.parameter, eklemek istediğimiz fragment object'dir.)
Once you've made your changes with
FragmentTransaction, you must call commit() for the changes to take effect. (FragmentTransaction object'de gerekli işlemleri yaptıktan sonra bu
değişiklikleri kaydetmek için FragmentTransaction
object'in commit() method'unu çağırmalıyız. )
Adding a fragment
without a UI
The
examples above show how to add a fragment to your activity in order to provide
a UI. However, you can also use a fragment to provide a background behavior for
the activity without presenting additional UI. (
Yukarıdaki örneklerdeki yarattığımız ve kullandığımız tüm fragment'ların bir
UI'ı vardı. Bu fragment'lar, bir activity'nin UI'nın bir parçası olarak
kullanılıyordu. Buna karşın,
UI'ı olmayan bir fragment da tanımlayabiliriz, UI'ı olmayan bir fragment activity'nin arka plandaki
bir davranış bir iş parçası olarak çalışır. )
To add a fragment without a UI, add
the fragment from the activity using add(Fragment, String tag) (supplying a
unique string "tag" for the fragment, rather than a view ID). ( UI'sız
bir fragment'ı activity'ye eklemek için add(Fragment,
String tag) method'unu çağırırız.
add() method'una 2.parameter olarak fragment'ın unique tag'ını veririz dikkat!!
fragment'ın layout'u yani UI'ı olmadığı için activity'nin layout XML dosyasında
fragment element de yoktur, fragment element olmadığı için fragment'ın id'si
android:id attribute'ü ile belirlenmemiştir. UI'sız bir fragment'ın id'si android:tag
attribute'ü kullanılarak belirlenir )
This adds
the fragment, but, because it's not associated with a view in the activity
layout, it does not receive a call to onCreateView(). So you don't need to
implement that method. ( Bir fragment, activity'nin
layout(UI)'undaki hiçbir view ile ilişkili değilse, yani fragment'ın bir UI'ı
yoksa onCreateView() method'u çağırılmaz, onCreateView() method'unu implement
etmemize de gerek yoktur. Çünkü onCreateView() method'unun fragment için bir
layout belirlemek için kullanıldığını hatırlayalım. )
Supplying a string tag
for the fragment isn't strictly for non-UI fragments—you can also supply string
tags to fragments that do have a UI—but if the fragment does not have a UI,
then the string tag is the only way to identify it. If you want to get the
fragment from the activity later, you need to use findFragmentByTag().(UI'sız bir fragment'ın id'sini sadece android:tag
kullanarak belirleyebiliriz. Ancak UI'lı bir fragment'ın id'sini android:tag
veya android:id kullanarak belirleyebiliriz. Activity içerisinde
findFragmentByTag() method'unu çağırarak fragment'ı elde edebiliriz, bu
method'a elde etmek istediğimiz fragment'ın unique tag string'ini argument olarak
veririz. )
For an
example activity that uses a fragment as a background worker, without a UI, see
the FragmentRetainInstance.java sample, which is included in the SDK samples
(available through the Android SDK Manager) and located on your system as <sdk_root>/APIDemos/app/src
/main/java/com/example/android/apis/app/FragmentRetainInstance.java. ( UI'sız bir fragment örneği görmek istiyorsanız, Android
SDK Manager ile birlikte gelen SDK örneklerindeki FragmentRetainInstance.java
örneğini inceleyebilirsiniz. )
Managing Fragments
To
manage the fragments in your activity, you need to use FragmentManager. To get
it, call getFragmentManager() from your activity. ( Activity'mizde fragmet'ları yönetmek için
activity'mizde getFragmentManager() method'Unu çağırarak FragmentManager object
elde ederiz. )
Some things that you can do with
FragmentManager include: (FragmentManager object'i
kullanarak şunları yapabiliriz : )
- Get fragments that exist in the
activity, with findFragmentById() (for fragments that provide a UI in the
activity layout) or findFragmentByTag() (for fragments that do or don't provide
a UI). (findFragmentById() method'unu çağırarak
activity'nin içerdiği UI'lı fragment'ları elde edebiliriz. findFragmentByTag()
method'unu çağırarak activity'nin içerdiği UI'lı veya UI'sız fragment'ları elde
edebiliriz. )
- Pop fragments off the back stack,
with popBackStack() (simulating a Back command by the user). back stack nedir? ( popBackStack() method'unu çağırarak back stack'dan
fragment'ları çıkartabiliriz. Bunu kullanıcının geri tuşuna bastığı case için
yaparız. )
- Register a listener for changes to
the back stack, with addOnBackStackChangedListener().(addOnBackStackChangedListener()
method'unu çağırarak, back stack'a bir listener kaydedebiliriz. Back stack'da
bir değişiklik olursa, back stack'a yeni bir fragment eklenirse veya varolan
bir fragment backstack'dan çıkartılırsa veya back stack'daki bir fragment
replace edilirse bize haber verilecektir backstack'a listener ile kaydolduğumuz
için. )
Performing
Fragment Transactions
A great feature
about using fragments in your activity is the ability to add, remove, replace,
and perform other actions with them, in response to user interaction.
Each set of
changes that you commit to the activity is called a transaction and you can
perform one using APIs in FragmentTransaction.
You can also
save each transaction to a back stack managed by the activity, allowing the
user to navigate backward through the fragment changes (similar to navigating
backward through activities).
(
User interaction'a response olarak activity'ye bir fragment eklenebilir,
çıkartılabilir, replace edilebilir. Bu işlemleri yaptıktan sonra activity'ye
yaptığımız herbir commit'e transaction denir,FragmentTransaction object
kullanılarak bu yapılabilir. Herbir transaction, activity tarafından yönetilen
bir back stack'a kaydedilebilir, kullanıcı geri tuşuna basarak activity'lerde
geri geldiği gibi fragment'larda da geri gelebilir. )
You can acquire
an instance of FragmentTransaction from the FragmentManager like this:
FragmentManager
fragmentManager = getFragmentManager();
FragmentTransaction
fragmentTransaction = fragmentManager.beginTransaction();
Each
transaction is a set of changes that you want to perform at the same time. You
can set up all the changes you want to perform for a given transaction using
methods such as add(), remove(), and replace(). Then, to apply the transaction
to the activity, you must call commit(). ( Herbir
transaction, aynı anda gerçekleştirmek istediğimiz bir veya daha fazla
değişikliği içerir. Örneğin, sadece bir transaction, 2 tane fragment ekleyip, 3
fragment çıkartabilir, 1 tanesini replace edebilir. Bu değişiklikleri aynı
FragmentTransaction object üzerinde yaptıktan sonra, transaction'ı activity'ye
uygulamak için commit() methodU'nu çağırmalıyız. )
Before you call commit(), however, you
might want to call addToBackStack(), in order to add the transaction to a back
stack of fragment transactions. This back stack is managed by the activity and
allows the user to return to the previous fragment state, by pressing the Back
button.
(fragment
transaction'ların back stack'ına bir transaction eklemek için, commit()
method'unu çağırmadan önce addToBackStack() method'unu çağırmalıyız. )
For example,
here's how you can replace one fragment with another, and preserve the previous
state in the back stack:
// Create new
fragment and transaction
Fragment
newFragment = new ExampleFragment();
FragmentTransaction
transaction = getFragmentManager().beginTransaction();
// Replace
whatever is in the fragment_container view with this fragment,
// and add the
transaction to the back stack
transaction.replace(R.id.fragment_container,
newFragment);
transaction.addToBackStack(null);
// Commit the
transaction
transaction.commit();
In this
example, newFragment replaces whatever fragment (if any) is currently in the
layout container identified by the R.id.fragment_container ID. ( Yukarıdaki örnekte bir fragment bir view ile replace
edilir. ExampleFragment class'ından newFragment isimli bir Fragment object
yaratılır.
transaction
isimli bir FragmentTransaction object yaratılır. transaction isimli object'in
replace method'u çağırılır.
fragment_container
isimli view'in içerisinde her ne varsa bunun ile newFragment isimli fragment object
replace edilir, yani fragment_container isimli view'in içindeki her şey
override edilecek newFragment tarafından. )
By calling addToBackStack(), the replace
transaction is saved to the back stack so the user can reverse the transaction
and bring back the previous fragment by pressing the Back button. (transaction.addToBackStack(null); denilerek, transaction
isimli object'e kaydedilen replace transaction işlemi back stack'a koyulur. Bu
sayede geri tuşuna basınca önceki fragment'a gelme özelliği sağlanmış
olur. )
If you add multiple changes to the
transaction (such as another add() or remove()) and call addToBackStack(), then
all changes applied before you call commit() are added to the back stack as a
single transaction and the Back button will reverse them all together. (transaction object üzerinde birden fazla
değişiklik(ekleme,çıkarma veya replace) yaptıysak, addToBackStack() method'unu
çağırınca tüm bu değişikilkler single bir transacation olarak backstack'a
koyulur, FragmentTransaction'a hangi sırayla değişiklik yaptımızın bir önemi
yoktur, önce ekleme sonra silme veya önce silme sonra ekleme aynı şeydir.
addToBackStack() method'unu çağırdıktan sonra commit() method'u çağırılarak
değişikilkler gerçekleştirilir. )
The order in
which you add changes to a FragmentTransaction doesn't matter, except:
- You must call
commit() last
- If you're
adding multiple fragments to the same container, then the order in which you
add them determines the order they appear in the view hierarchy
(
FragmentTransaction'a hangi sırayla değişiklik yaptığımızın bir önemi yoktur,
önce ekleme sonra silme veya önce silme sonra ekleme aynı şeydir. Şu sıra ise
önemlidir dikkat edilmelidir :
-
commit() method'u en son çağırılmalıdır.
-
Bir container'a birden fazla fragment ekleyeceksek, hangi fragment'ı önce hangi
fragment'ı sonra eklediğimiz önemlidir, sıra önemlidir, fragment'ları hangi
sırayla eklediğimiz view hierarchy'de fragment'ların hangi sırayla görüneceğini
belirler. )
If you do not
call addToBackStack() when you perform a transaction that removes a fragment,
then that fragment is destroyed when the transaction is committed and the user
cannot navigate back to it.
Whereas, if you
do call addToBackStack() when removing a fragment, then the fragment is stopped
and will be resumed if the user navigates back. (
Bir fragment'ı bir activity'den silen bir transaction'ı commit() ettik diyelim.
Commit etmeden önce addToBackStack() method'unu çağırmadık diyelim. Bu case'de,
transaction commit edilince fragment yok edilir, kullanıcı geri tuşunu
kullanarak bu fragment'a geri gelemez artık.
Commit
etmeden önce addToBackStack() method'unu çağırmışsak, fragment stack'a
konulmuştur, kullanıcı geri tuşunu
kullanarak bu fragment'a geri gelebilir.
)
Tip: For each
fragment transaction, you can apply a transition animation, by calling
setTransition() before you commit.( Herbir fragment
transition için, setTransition() method'U çağırılara bir transition animation
uygulanabilir. )
executePendingTransactions()
Calling
commit() does not perform the transaction immediately. Rather, it schedules it
to run on the activity's UI thread (the "main" thread) as soon as the
thread is able to do so.
If necessary,
however, you may call executePendingTransactions() from your UI thread to
immediately execute transactions submitted by commit().
Doing so is
usually not necessary unless the transaction is a dependency for jobs in other
threads.
(
commit() method'unu çağırdığımızda, transaction anında gerçekleşmez. main UI'da
yani activity'nin UI thread'inde çalışacak şekilde schedule edilir, yani thread
müsait olunca transaction gerçekleşir. Eğer UI thread'in commit() edilen
transaction'ları anında gerçekleştirmesini istiyorsak
executePendingTransactions() method'unu çağırmalıyız. Eğer diğer thread'lerde
işler için bu bir dependency ise kullanmalıyız bu method'u, gereksiz yere
kullanmamalıyız. )
Performing
Fragment Transactions
Caution: You
can commit a transaction using commit() only prior to the activity saving its
state (when the user leaves the activity). If you attempt to commit after that
point, an exception will be thrown.
This is because
the state after the commit can be lost if the activity needs to be restored.
For situations in which its okay that you lose the commit, use
commitAllowingStateLoss(). ( Bir transaction'ı,
activity state'ini kaydetmeden önce commit etmeliyiz, yani kullanıcı
activity'den ayrılmadan önce transaction'ı commit etmeliyiz. Aksi takdirde
exception olur. )
Communicating
with the Activity
Although a Fragment is implemented as an
object that's independent from an Activity and can be used inside multiple
activities, a given instance of a fragment is directly tied to the activity
that contains it. ( Fragment, Activity'den bağımsız
bir object olarak implement edilir. Fragment, birden falz activity içerisinde
kullanılabilir. Buna karşın, fragment bağlı olduğu activity'den bağımsız
değildir, bağlıdır, onunla haberleşebilir. )
Specifically, the fragment can access the
Activity instance with getActivity() and easily perform tasks such as find a
view in the activity layout: ( Fragment object'de,
getActivity() method'Unu çağırarak fragment'I içeren activity'yi elde ederiz,
activity'yi elde ettikten sonra activity'nin layout'undaki view'leri de
kolaylıkla elde edebiliriz. )
Örnek
:
View listView =
getActivity().findViewById(R.id.list); // fragment
object'den, içerisinde olduğu actiivty'deki list id'li view'i elde ederiz.
Likewise, your
activity can call methods in the fragment by acquiring a reference to the Fragment
from FragmentManager, using findFragmentById() or findFragmentByTag().
(
Activity'den fragment'a erişmek için, FragmentManager object'in
findFragmentById() veya findFragmentByTag() method'unu çağırırız. )
Örnek:
ExampleFragment fragment = (ExampleFragment)
getFragmentManager().findFragmentById(R.id.example_fragment);
Creating
event callbacks to the activity
In some cases,
you might need a fragment to share events with the activity. A good way to do
that is to define a callback interface inside the fragment and require that the
host activity implement it.
When the
activity receives a callback through the interface, it can share the
information with other fragments in the layout as necessary.
(
fragment içerisinde bir interface declare ederiz. Host activity'de bu
interface'i implement ederiz. Bu sayede fragment, activity ile event
paylaşabilir(haberleşebilir). Bu fragment, bu interface'deki bir method'u
çağırdığında activity bundan haberdar olur ve kendisine gelen bilgiyi diğer
fragment'larla paylaşabilir. )
For example, if
a news application has two fragments in an activity—one to show a list of
articles (fragment A) and another to display an article (fragment B)—then
fragment A must tell the activity when a list item is selected so that it can
tell fragment B to display the article.
In this case,
the OnArticleSelectedListener interface is declared inside fragment A: ( Bir activity, 2 fragment içerir : FragmentA ve
FragmentB. FragmentA haber başlıklarını, FragmentB haber detaylarını içerir.
FragmentA'daki
bir haber başlığı seçilince, FragmentA bunu host activity'ye söyler, host
activity de bunu Fragment B'ye söyler, böylece Fragment B ilgili haber detayını
gösterir. Bu mekanizmayı şöyle kurarız :
FragmentA
class'ında OnArticleSelectedListener isimli bir interface declare edilir. )
public static
class FragmentA extends ListFragment {
...
// Container Activity must implement this
interface
public interface OnArticleSelectedListener
{
public void onArticleSelected(Uri
articleUri);
}
...
}
Then the
activity that hosts the fragment implements the OnArticleSelectedListener
interface and overrides onArticleSelected() to notify fragment B of the event
from fragment A.
To ensure that
the host activity implements this interface, fragment A's onAttach() callback
method (which the system calls when adding the fragment to the activity)
instantiates an instance of
OnArticleSelectedListener
by casting the Activity that is passed into onAttach():
(
Host activity OnArticleSelectedListener interface'ini implement eder ve
onArticleSelected() method'Unu override eder.
Host
activity'nin bu interface'i implement ettiğinden emin olmak için fragment A'nın
onAttach() isimli callback method'unda aşağıdaki kod yazılır. onAttach()
method'Unun aldığı parametre olan Activity object OnArticleSelectedListener
interface type'ına cast edilmeye çalışır.
Bu,
try catch block'da yapılır. )
public static
class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener =
(OnArticleSelectedListener) activity;
} catch (ClassCastException e) {
throw new
ClassCastException(activity.toString() + " must implement
OnArticleSelectedListener");
}
}
...
}
If the activity
has not implemented the interface, then the fragment throws a
ClassCastException.
On success, the
mListener member holds a reference to activity's implementation of
OnArticleSelectedListener,
so that
fragment A can share events with the activity by calling methods defined by the
OnArticleSelectedListener interface.
For example, if
fragment A is an extension of ListFragment, each time the user clicks a list
item, the system calls onListItemClick() in the fragment,
which then
calls onArticleSelected() to share the event with the activity:
(
Host activity, bu interface'i implement etmemişse, fragment A
ClassCastException fırlatır.
Host
activity, bu interface'i implement etmişse, mListener isimli variable host
activity'deki OnArticleSelectedListener interface'inin implementation'ına refer
eder.
Artık
fragmentA OnArticleSelectedListener interface'inde tanımlı method'ları
çağırabilir, yani host activity ile event share edebilir.
Örneğin,
fragment A ListFragment'ı extend eden bir class olsun. Bu durumda kullanıcı
listedeki item'lardan birine tıklayınca, fragmentA class'ında tanımlı olan
onListItemClick() method'U çağırılır otomatik olarak.
Bu
method içerisinde de onArticleSelected() method'u çağırılarak host activity ile
event share edilir. )
public static
class FragmentA extends ListFragment {
OnArticleSelectedListener mListener;
...
@Override
public void onListItemClick(ListView l,
View v, int position, long id) {
// Append the clicked item's row ID
with the content provider Uri
Uri noteUri =
ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
// Send the event and Uri to the host
activity
mListener.onArticleSelected(noteUri);
}
...
}
The id
parameter passed to onListItemClick() is the row ID of the clicked item, which
the activity (or other fragment) uses to fetch the article from the
application's ContentProvider.( onListItemClick()
method'unu aldığı id parameter, listedeki tıklanılan item'ın row id'sidir. )
Handling
the Fragment Lifecycle
Figure 3. The effect of the
activity lifecycle on the fragment lifecycle.
Handling
the Fragment Lifecycle
Managing the
lifecycle of a fragment is a lot like managing the lifecycle of an activity.
Like an activity, a fragment can exist in three states:
Resumed
The fragment is
visible in the running activity.
Paused
Another
activity is in the foreground and has focus, but the activity in which this
fragment lives is still visible (the foreground activity is partially
transparent or doesn't cover the entire screen).
Stopped
The fragment is
not visible. Either the host activity has been stopped or the fragment has been
removed from the activity but added to the back stack. A stopped fragment is
still alive (all state and member information is retained by the system).
However, it is no longer visible to the user and will be killed if the activity
is killed.
Also like an
activity, you can retain the state of a fragment using a Bundle, in case the
activity's process is killed and you need to restore the fragment state when
the activity is recreated.
You can save
the state during the fragment's onSaveInstanceState() callback and restore it
during either onCreate(), onCreateView(), or onActivityCreated().
The most
significant difference in lifecycle between an activity and a fragment is how
one is stored in its respective back stack.
An activity is
placed into a back stack of activities that's managed by the system when it's
stopped, by default
(so that the
user can navigate back to it with the Back button, as discussed in Tasks and
Back Stack).
However, a
fragment is placed into a back stack managed by the host activity only when you
explicitly request that the instance be saved by calling addToBackStack()
during a transaction that removes the fragment.
Otherwise,
managing the fragment lifecycle is very similar to managing the activity
lifecycle. So, the same practices for managing the activity lifecycle also
apply to fragments.
What you also
need to understand, though, is how the life of the activity affects the life of
the fragment.
Caution: If you
need a Context object within your Fragment, you can call getActivity(). (
Fragment class'ının içerisinde Context object'i elde etmek için getActivity()
method'unu çağırmalıyız. )
However, be
careful to call getActivity() only when the fragment is attached to an
activity. When the fragment is not yet attached, or was detached during the end
of its lifecycle, getActivity() will return null.
(
Fragment bir activity'nin içine gömüldükten sonra çağırmaya dikkat et
getActivity() method'unu. Aksi takdirde, getActivity() method'u null return
eder. )
Coordinating
with the activity lifecycle
The lifecycle
of the activity in which the fragment lives directly affects the lifecycle of
the fragment, such that each lifecycle callback for the activity results in a
similar callback for each fragment.
For example,
when the activity receives onPause(), each fragment in the activity receives
onPause().
Fragments have
a few extra lifecycle callbacks, however, that handle unique interaction with
the activity in order to perform actions such as build and destroy the
fragment's UI.
These
additional callback methods are:
onAttach()
Called when the
fragment has been associated with the activity (the Activity is passed in
here).
onCreateView()
Called to
create the view hierarchy associated with the fragment.
onActivityCreated()
Called when the
activity's onCreate() method has returned.
onDestroyView()
Called when the
view hierarchy associated with the fragment is being removed.
onDetach()
Called when the
fragment is being disassociated from the activity.
The flow of a
fragment's lifecycle, as it is affected by its host activity, is illustrated by
figure 3.
In this figure,
you can see how each successive state of the activity determines which callback
methods a fragment may receive.
For example,
when the activity has received its onCreate() callback, a fragment in the
activity receives no more than the onActivityCreated() callback.
Once
the activity reaches the resumed state, you can freely add and remove fragments
to the activity. Thus, only while the activity is in the resumed state can the
lifecycle of a fragment change independently.
However, when
the activity leaves the resumed state, the fragment again is pushed through its
lifecycle by the activity.
Bu dersin tamamının pdf'ini linkten indirebilirsiniz: https://drive.google.com/file/d/197jW8LhSU6HJz35rIIiqN1mDM8m6rT_3/view?usp=sharing
Bu dersin tamamının pdf'ini linkten indirebilirsiniz: https://drive.google.com/file/d/197jW8LhSU6HJz35rIIiqN1mDM8m6rT_3/view?usp=sharing
Hiç yorum yok:
Yorum Gönder