Освой программирование играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Доступ к View внутри фрагмента

Доступ к View внутри динамического фрагмента из активности
Передача данных между фрагментами

Так как существует два способа использования фрагментов в активности, то взаимодействие между компонентами, которые находятся внутри фрагментов немного отличается.

Доступ к 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. Давайте создадим разметку для фрагмента.

res/layout/fragmentlayout.xml


<?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);

Создадим разметки для двух фрагментов. В одном разместим текстовое поле, а во втором кнопку и текстовую метку, в которой будем выводить текст из текстового поля первого фрагмента:

res/layout/redfragment.xml


<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>

res/layout/bluefragment.xml


<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());
	}
}

Мы получаем ссылки на все компоненты и обрабатываем щелчок мыши. В разметку активности добавьте два созданных фрагмента и запустите пример. Введите какой-нибудь текст в текстовом поле (напоминаю, что он относится к первому фрагменту). Нажмите на кнопку, которая относится ко второму фрагменту. В текстовой метке второго фрагмента появится введённым вами текст.

Реклама