Освой программирование играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Доступ к View внутри динамического фрагмента из активности
Передача данных между фрагментами
Так как существует два способа использования фрагментов в активности, то взаимодействие между компонентами, которые находятся внутри фрагментов немного отличается.
Рассмотрим пример доступа к компоненту, который находится внутри динамического фрагмента из активности.
Фрагмент может иметь собственную разметку и содержать различные компоненты View: TextView, EditText и т.д. Напрямую из активности обратиться к нужному компоненту и поменять, например, текст в TextView не получится. А как же достучаться до нужного компонента? Рассмотрим простой пример.
Создадим класс фрагмента MyFragment.java:
package ru.alexanderklimov.fortest;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MyFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View myFragmentView = inflater.inflate(R.layout.fragmentlayout,
container, false);
return myFragmentView;
}
}
В методе onCreateView() мы указали ресурс разметки R.layout.fragmentlayout. Давайте создадим разметку для фрагмента.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Fragment:" />
<TextView
android:id="@+id/fragmenttext"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
В данной разметке нас интересует вторая текстовая метка с идентификатором fragmenttext.
Создадим разметку для основной активности:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Activity:" />
<EditText
android:id="@+id/activitytext"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/sendtofragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send Text to Fragment" />
</LinearLayout>
<LinearLayout
android:id="@+id/myfragment"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
Последняя компоновка LinearLayout с идентификатором myfragment является контейнером для фрагмента, который будет его замещать. Напишем код для главной активности:
public class TestActivity extends Activity {
EditText textActivity;
Button buttonSendToFragment;
MyFragment myFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
textActivity = (EditText) findViewById(R.id.activitytext);
buttonSendToFragment = (Button) findViewById(R.id.sendtofragment);
// получим экземпляр FragmentTransaction из нашей Activity
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
// добавляем фрагмент
myFragment = new MyFragment();
fragmentTransaction.add(R.id.myfragment, myFragment);
fragmentTransaction.commit();
buttonSendToFragment.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String text = textActivity.getText().toString();
TextView textFragment = (TextView) findViewById(R.id.fragmenttext);
textFragment.setText(text);
}
});
}
}
При запуске программы мы получаем экземпляр класса FragmentTransaction и добавляем фрагмент на экран вместо LinearLayout. Теперь текстовая метка фрагмента доступна для изменения - получаем ссылку на нужный компонент и устанавливаем требуемый текст.
Когда мы заменяем контейнер своим фрагментом, то он становится частью активности и получаем доступ к компонентам стандартным способом, как в примере выше. Если мы используем фрагменты как самостоятельные элементы, то доступ к компонентам происходит немного по-другому. Так как фрагменты не существуют сами по себе, а только внутри активности, то сначала нужно получить доступ к родительской активности через метод getActivity(), а затем уже можно получить доступ к нужному компоненту из фрагмента:
TextView tvInfo = (TextView)getActivity().findViewById(R.id.textView);
Создадим разметки для двух фрагментов. В одном разместим текстовое поле, а во втором кнопку и текстовую метку, в которой будем выводить текст из текстового поля первого фрагмента:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/red_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_red_light"
android:orientation="vertical" >
<TextView
android:id="@+id/tvMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Красный фрагмент" />
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/blue_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_blue_light"
android:orientation="vertical" >
<TextView
android:id="@+id/tvGetMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Синий фрагмент" />
<Button
android:id="@+id/butGetText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Прочитать данные" />
</LinearLayout>
В код первого фрагмента добавим только наполнение из разметки:
package ru.alexanderklimov.test;
import ...
public class RedFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
// Возвращаем объект View из разметки фрагмента
return inflater.inflate(R.layout.redfragment, container, false);
}
}
В класс второго фрагмента добавим код для чтения данных из первого фрагмента. Сделаем это в методе onStart():
package ru.alexanderklimov.test;
import ...
public class BlueFragment extends Fragment implements OnClickListener {
private TextView tvGetMsg;
private EditText edit;
private Button butGetMsg;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
// Возвращаем объект View из разметки фрагмента
return inflater.inflate(R.layout.bluefragment, container, false);
}
@Override
public void onStart() {
// TODO Auto-generated method stub
super.onStart();
tvGetMsg = (TextView)getActivity().findViewById(R.id.tvGetMessage);
edit = (EditText)getActivity().findViewById(R.id.editText);
butGetMsg = (Button)getActivity().findViewById(R.id.butGetText);
butGetMsg.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
tvGetMsg.setText(edit.getText());
}
}
Мы получаем ссылки на все компоненты и обрабатываем щелчок мыши. В разметку активности добавьте два созданных фрагмента и запустите пример. Введите какой-нибудь текст в текстовом поле (напоминаю, что он относится к первому фрагменту). Нажмите на кнопку, которая относится ко второму фрагменту. В текстовой метке второго фрагмента появится введённым вами текст.