Neste tutorial vai ser explicada a utilização de fragmentos na aplicação. Mais uma vez, iremos recorrer a ficheiros .xml para nos facilitar a vida. Iremos introduzir o conceito de permissões, visto que iremos precisar para aceder à net. O objetivo deste tutorial é criar uma aplicação de raiz (para isso o leitor pode já começar a criar um novo projeto com uma empty activity) e, ter uma lista dos três clubes grandes de Portugal (Porto, Sporting e Benfica), clicar em um deles e transitar para outro fragmento que me irá dar uma página da wikipédia na minha aplicação.
Ficheiros .xml
O primeiro passo será criar um ficheiro .xml com um array de strings. Para isso, basta criar um novo .xml dentro da pasta “values” com o nome “equipas.xml” como podemos ver a seguir:
e, o conteúdo do ficheiro deverá então ser 2 arrays de strings. Um com o nome dos 3 clubes e o outro com os links de onde queremos ir buscar a informação dos mesmos:
<resources> <string-array name="equipas"> <item>FCPorto</item> <item>SportingCP</item> <item>SLBenfica</item> </string-array> <string-array name="paginas"> <item>https://pt.wikipedia.org/wiki/Futebol_Clube_do_Porto</item> <item>https://pt.wikipedia.org/wiki/Sport_Lisboa_e_Benfica</item> <item>https://pt.wikipedia.org/wiki/Sporting_Clube_de_Portugal</item> </string-array> </resources>
Para mais informação sobre os passos realizados neste capitulo, rever o tutorial anterior aqui.
Fragmentos
Para podermos proceder à criação dos layouts sem erros, teremos de adicionar fragmentos na nossa pasta de código java. Para isso, basta procedermos da seguinte forma (dois passos):
- Note-se que deverá utilizar os mesmos nomes que no tutorial para evitar erros
Em cima iremos criar um fragment list. Este será um fragmento que terá uma lista. A geração da classe irá gerar código que, todo ele será inútil. A classe deverá ter o seguinte código:
public class ListFragmentLinks extends ListFragment { boolean dualFrame; int curPosition = 0; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Creates the list from the array defined in the XML file, using an ArrayAdapter setListAdapter(ArrayAdapter.createFromResource(getActivity(), R.array.equipas, android.R.layout.simple_list_item_activated_1)); // Is a frame for details available ? View detailsFrame = getActivity().findViewById(R.id.details); //Are we in dual frame mode ? dualFrame = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE; if (savedInstanceState != null) { // Restore the last state for the chosen position curPosition = savedInstanceState.getInt("curPosition", 0); } if (dualFrame) { getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); showDetails(curPosition); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("curPosition", curPosition); } @Override public void onListItemClick(ListView l, View v, int position, long id){ showDetails(position); } //Show details for the selected item private void showDetails(int index) { curPosition = index; if (dualFrame) { getListView().setItemChecked(index, true); // Check which fragment is being shown and modify it if necessary ClubesFragment details = (ClubesFragment) getFragmentManager().findFragmentById(R.id.details); if (details == null || details.getShownIndex() != index) { // Create a new fragment details = ClubesFragment.newInstance(index); // Replacement transaction FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.details, details); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); ft.commit(); } } else { // Replace existing fragment with the one instantiated using a factory method ClubesFragment details = ClubesFragment.newInstance(index); FragmentTransaction ft=getFragmentManager().beginTransaction(); ft.replace(R.id.links, details); ft.addToBackStack("MAIN"); ft.commit(); } } }
O leitor deve dar especial atenção às seguintes situações no código:
- getFragmentManager()
- Gestor de fragmentos da aplicação
- FragmentTransaction ft = getFragmentManager().beginTransaction();
- Prepara transação na aplicação
- ft.replace(…)
- irá fazer a substituição de um fragmento por outro
- ft.setTransition(…)
- Animação para a transição a ocorrer
- ft.commit()
- Faz um commit da transação, passando assim de um fragmento para outro
Para terminar com o capitulo de fragmentos, o utilizador deverá criar agora outro fragment mas, um “Fragment (Blank)” e não um “Fragment (List)” uma vez que não precisamos de uma lista mas sim apenas de um fragmento:
O código da classe terá como objetivo criar uma WebView na nossa aplicação de acordo com o que colocámos no array de strings com o nome “páginas”. Ele irá buscar a página com a informação, neste caso da wikipédia, assim que escolhermos qual a informação do clube que queremos aceder. O código é:
public class ClubesFragment extends Fragment { // Create a new Detail Fragment instance public static ClubesFragment newInstance(int index) { ClubesFragment cdf = new ClubesFragment(); Bundle args = new Bundle(); args.putInt("index", index); cdf.setArguments(args); return cdf; } public int getShownIndex() { return getArguments().getInt("index", 0); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final String[] links = getResources().getStringArray(R.array.paginas); ScrollView scroller = new ScrollView(getActivity()); WebView webview = new WebView(getActivity()); webview.setWebViewClient(new SwAWebClient()); int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getActivity().getResources().getDisplayMetrics()); webview.setPadding(padding, padding, padding, padding); scroller.addView(webview); webview.loadUrl(links[getShownIndex()]); return scroller; } private class SwAWebClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return false; } } }
Layouts
Com a nossa MainActivity criada de forma “limpa”, chega então a parte mais complicada do trabalho. A criação dos layouts. Ao contrário do que temos feito anteriormente, neste tutorial os layouts serão criados manualmente. Ou seja, dentro da pasta layout, realizar o passo que se demonstrou na imagem em cima mas, dentro da pasta “values” e criar um .xml novo com o nome “lands.xml” com o seguinte conteúdo:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment class="org.blowstuff.fragmentstestetutorial.ListFragmentLinks" android:id="@+id/links" android:layout_weight="1" android:layout_width="0px" android:layout_height="match_parent" /> <FrameLayout android:id="@+id/details" android:layout_weight="1" android:layout_width="0px" android:layout_height="match_parent" /> </LinearLayout>
Vendo no formato “design”, poderemos ver que foi adicionado um fragmento (que será onde iremos ter links) e, um layout da frame.
No que toca a activity_main.xml, como não poderia deixar de ser, terá de ser alterada. O código é o seguinte:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment class="PACKAGE_NAME.ListFragmentsLinks" android:id="@+id/links" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
O leitor não deve esquecer de por o nome da package em PACKAGE_NAME.
A aplicação está pronta a correr, ou não?
Permissões
Caso o leitor tenha corrido a aplicação, certamente deverá ter tido um erro no pedido da página web. Isto porque para desenvolver em android é preciso permissões para quase tudo. É necessário o programador especificar no seu android manifest a permissão de que a aplicação pode aceder à internet da seguinte forma (poderá colocar antes da tag “application”):
<uses-permission android:name="android.permission.INTERNET"/>