Как стать автором
Обновить

Android: используем Fragments для оптимизации интерфейса

Время на прочтение6 мин
Количество просмотров67K
Добрый день. Сегодня я хотел бы показать вам небольшой и достаточно простой пример использования Fragments. Я надеюсь он будет полезен тем, кто только начал знакомиться с принципами работы Fragments. Изначально, фрагменты были реализованы начиная с Android 3.0 для более динамичного проектирования пользовательских интерфейсов.
Вкратце, Fragment схож с Activity, у них обоих есть свой собственный жизненный цикл. Однако Fragment не может существовать вне Activity. Можно использовать для одного и того же Activity разные Fragments что придает гибкость и вариативность в процессе разработки.

Больше про Fragments можно прочесть здесь:
Fragments. Android Developer

Перейдем же наконец к практике. Напишем небольшую тренировочную программу, в которой будут использоваться фрагменты. При вертикальном положении экрана сначала будет выведен статический список ссылок и при нажатии на ссылку, будет запускаться Activity, отображающее содержимое веб-страницы по выбранной ссылке. При горизонтальном положении экрана, список ссылок и содержимое веб-страницы будут размещаться во Fragments и отображаться одновременно. Схема работы приложения выглядит следующим образом:

image

Напишем класс FragmentActivity, именно с него начинается работа приложения:

public class FragmentActivity extends Activity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	setContentView(R.layout.fragment);
	}
}


Далее необходимо создать layout в файле fragment.xml для вертикальной и горизонтальной ориентации экрана, который используется в классе FragmentActivity. Для горизонтальной ориентации определим два фрагмента, каждый будет занимать по половине ширины экрана устройства. Содержимое файла /res/layout-land/fragment.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="horizontal" >

	<fragment class="com.example.hellopeacefullworld.FragmentList"
    	android:id="@+id/fragment_list"
    	android:layout_weight="1"
    	android:layout_width="match_parent"
    	android:layout_height="match_parent" >
	</fragment>

	<fragment class="com.example.hellopeacefullworld.FragmentDetail"
    	android:id="@+id/fragment_detail"
    	android:layout_weight="1"
    	android:layout_width="match_parent"
    	android:layout_height="match_parent" >
	</fragment>

</LinearLayout>


Содержимое файла /res/layout/fragment.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="horizontal" >

	<fragment class="com.example.hellopeacefullworld.FragmentList"
    	android:id="@+id/fragment_list"
    	android:layout_width="match_parent"
    	android:layout_height="match_parent" >
	</fragment>
</LinearLayout>


Опишем layout файл /res/layout/fragment_detail_activity.xml для Activity, которое будет отображать содержимое веб-страницы в вертикальной(портретной) ориентации:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical" >

	<fragment class="com.example.hellopeacefullworld.FragmentDetail"
    	android:id="@+id/fragment_detail"
    	android:layout_width="match_parent"
    	android:layout_height="match_parent" >
	</fragment>
</LinearLayout>


Сам класс Activity. В нем считываем полученную через extras ссылку и отображаем в WebView содержимое веб-страницы. Данное Activity вызывается в вертикальной ориентации:

public class FragmentDetailActivity extends Activity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	setContentView(R.layout.fragment_detail_activity);
    	Bundle extras = getIntent().getExtras();
    String s = extras.getString("selectedValue");
    WebView viewer = (WebView) findViewById(R.id.webView1);
    viewer.loadUrl(s);
 }
}


Класс FragmentList самый объемный, но не сложный в реализации. В функции onListItemClick мы проверяем наличие FragmentDetail с WebView. Если такой фрагмент существует, то вызываем его функцию goToLink(String link), которая загружает веб-страницу. В противном случае, если фрагмента не существует, то вызывается FragmentDetailActivity, в которое передается ссылка через extras.

public class FragmentList extends ListFragment {
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);
      String[] values = new String[] {
   	 "http://mobile.tutsplus.com/tutorials/mobile-design-tutorials/80s-phone-app-slicing/",
   	 "http://mobile.tutsplus.com/tutorials/corona/create-a-brick-breaker-game-with-the-corona-sdk-game-controls/",
   	 "http://mobile.tutsplus.com/articles/news/best-of-tuts-in-february-2011/"};
      ArrayAdapter adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, values);
      setListAdapter(adapter);
     }

     @Override
     public void onListItemClick(ListView l, View v, int position, long id) {
   	 String item = (String) getListAdapter().getItem(position);
     	 FragmentDetail fragment = (FragmentDetail)getFragmentManager().findFragmentById(R.id.fragment_detail);
     	 if (fragment != null && fragment.isInLayout()) {
   		 fragment.goToLink(item);
     	 } else {
      		 Intent intent = new Intent(getActivity().getApplicationContext(), FragmentDetailActivity.class);
      		 intent.putExtra("selectedValue", item);
      		 startActivity(intent);
          }
     }    
}


Опишем класс FragmentDetail, он будет служить для отображения содержимого веб-страницы в WebView. В частности, отображением занимается функция goToLink(String link), она вызывается в классе FragmentList.

public class FragmentDetail extends Fragment {
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
   	Bundle savedInstanceState) {
   	  View view = inflater.inflate(R.layout.fragment_detail, container, false);
   	  return view;
     }
    
     public void goToLink(String item){
   	  WebView viewer = (WebView)getView().findViewById(R.id.webView1);
   	  viewer.loadUrl(item);
     }
}


Файл fragment_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical" >

	<WebView
    	android:id="@+id/webView1"
    	android:layout_width="match_parent"
    	android:layout_height="match_parent" />
    
</LinearLayout>


Ну вот и все. Теперь запустим наше приложение. Результат работы должен быть следующим:




Спасибо за внимание.

UPDATE 1:
Спасибо пользователю vtimashkov за дельное замечание, которое находится в первом комментарии к статье. Ниже приведу код, решающий данную проблему,.

Итак, для начала внесем в файл AndroidManifest следующие изменения:

<activity android:name=".FragmentDetailActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"></activity>


Это позволит нам контролировать изменение ориентации экрана в FragmentDetailActivity. Далее изменим функциональность класса FragmentDetailActivity. Сохраняем текущую ссылку в переменную currentLink. Функция onConfigurationChanged вызывается при смене ориентации экрана. В ней, проверяем, если мы попали с вертикального режима в горизонтальный, то запускаем FragmentActivity и передаем в него текущую ссылку.

public class FragmentDetailActivity extends Activity {
	
	String currentLink;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.fragment_detail_activity);
		Bundle extras = getIntent().getExtras();
		currentLink = extras.getString("selectedValue");
		WebView viewer = (WebView) findViewById(R.id.webView1);
		viewer.loadUrl(currentLink);
	}	
    
	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
			Intent intent = new Intent(this, FragmentActivity.class);
			intent.putExtra("selectedValue", currentLink);
			startActivity(intent);
		} 
	}
}



И наконец наш FragmentActivity. Сперва проверяем, получили ли мы ссылку в extras. Если да, то это означает, что мы перешли в FragmentDetailActivity в горизонтальный режим и теперь отображаем содержимое веб-страницы в.

public class FragmentActivity extends Activity {
@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.fragment);
		FragmentDetail fragment = 
			(FragmentDetail)getFragmentManager().findFragmentById(R.id.fragment_detail);
		Bundle extras = getIntent().getExtras();
		if(extras != null){
				String link = extras.getString("selectedValue");
				if(link !=null && fragment != null && fragment.isInLayout()){
					fragment.goToLink(link);
				}
		}
	}
}
Теги:
Хабы:
Всего голосов 11: ↑9 и ↓2+7
Комментарии10

Публикации