Solucionado (ver solução)
Solucionado
(ver solução)
10
respostas

Fechar e Abrir diversos fragments

Bom dia, tudo certo?

Estou com uma dúvida. Seguinte:

Eu tenho 1 Activity, e entrando nela, abre automaticamente o Fragment_01, onde o usuário escolhe um item da lista e abre o Fragment_02, onde novamente ele escolhe um item e abre o Fragment_03.

No Fragment_03, ele pode acessar um site, que abre via navegador do celular. Mas ao fechar o navegador, o app está na tela do Fragment_02, sendo que deveria ter continuado no Fragment_03.

01 - Como fazer para não fechar o Fragment_03 quando o usuário clicar no site e abrir o navegador?

02 - Seria correto fechar cada Fragment assim que passo para o próximo? Qual seria o comando para fazer isso?

Obrigado.

10 respostas

Tenta fazer algo desse genero

Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
startActivity(browserIntent);

Seria melhor você postar o código fonte atual, para entender o que está acontecendo.

Olá Nicolas,

Vamos começar pela segunda dúvida. Quando você utiliza a operação replace(...) na FragmentTransaction, o Android se encarrrega de encerrar o fragment que está sendo substituído.

Agora na sua primeira dúvida, parece estranho que ele volte no segundo fragment. O que eu esperaria seria que ele voltasse no terceiro fragment normalmente a não ser que a activity tenha sido destruída (improvável no cenário que você descreveu). Mesmo que a activity tivesse sido destruída, deveria ter voltado no primeiro fragment. Para termos certeza do que está acontecendo vou pedir para você postar aqui o código da sua activity e dos seus fragments.

De qualquer maneira, a forma correta de lidar com esse tipo de coisa é utilizar os métodos do ciclo de vida da activity para salvar qual o fragment selecionado e quando você retornar para a activity, recarregar o fragment correspondente ao que você tinha armazenado.

Eu acho que me confundi, ele volta sim para o 1º Fragment.

É que são várias telas, coloco todas aqui??

Basicamente a Activity inicia colocando um 1º Fragment, que faz uma AsyncTASK com um webservice, gerando um ListView.

Desse ListView, escolho um item e vou para o 2º Fragment que faz outra AsyncTASK com o webservice, gerando mais um ListView.

Novamente selecionado, ele vai para o 3º Fragment, que faz outra AsyncTASK com o webservice, carregando os dados em um CardView.

Nesse 3º Fragment eu coloquei um Listener em um TextView, que ao ser clicado abre o site no navegador, mas ao fechar o navegador, ele volta ao 1º Fragment.

Caso precise colocar o código, coloco todas as telas, ou apenas os Fragments já basta?

PS: Esse Listener abre um PopupMenu que ao ser clicado vai para o navegador:


case R.id.menu_item_site:
    TextView txtSite = (TextView) view.findViewById(R.id.main_empresa_site);
    String site = (String) txtSite.getText();

    Intent intentSite = new Intent(Intent.ACTION_VIEW);

    if (!site.startsWith("http://")) {
        site = "http://" + site;
     }

    intentSite.setData(Uri.parse(site));
    startActivity(intentSite);
    return true;

Olá Nicolas,

Acho melhor você postar o código completo das activities, fragments e asynctasks, só para a gente ter uma ideia melhor do fluxo do aplicativo.

Bom dia, tudo bem?

Segue o código da Activity e fragment. É basicamente o mesmo para os fragments em sequência, buscar uma informação no webservice através de uma task e carregar uma lista.

Quando estou no 3º Fragment, ao clicar e abrir o site via navegador do android, ele volta para esta Activity principal.

MainActivity:

package br.com.teste;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;

import br.com.teste.modelo.Categoria;
import br.com.teste.modelo.Cidade;
import br.com.teste.modelo.Empresa;

public class MainActivity extends AppCompatActivity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    protected void onResume() {
        super.onResume();
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction tx = manager.beginTransaction();
        MainFragmentListaCategorias fragmentListaCategorias = new MainFragmentListaCategorias();

        Intent intent = getIntent();
        Cidade cidade = (Cidade) intent.getSerializableExtra("cidade");

        Bundle params = new Bundle();
        params.putSerializable("cidade", cidade);
        fragmentListaCategorias.setArguments(params);

        tx.replace(R.id.frame_principal, fragmentListaCategorias);
        tx.commit();
    }

    public void carregaCategoria(Cidade cidade, Categoria categoria) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction tx = manager.beginTransaction();
        MainFragmentListaEmpresas fragmentListaEmpresas = new MainFragmentListaEmpresas();

        Bundle params = new Bundle();
        params.putSerializable("cidade", cidade);
        params.putSerializable("categoria", categoria);
        fragmentListaEmpresas.setArguments(params);

        tx.replace(R.id.frame_principal, fragmentListaEmpresas);
        tx.addToBackStack(null);
        tx.commit();
    }

    public void carregaEmpresa(Empresa empresa) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction tx = manager.beginTransaction();
        MainFragmentEmpresa fragmentEmpresa = new MainFragmentEmpresa();

        Bundle params = new Bundle();
        params.putSerializable("empresa", empresa);
        fragmentEmpresa.setArguments(params);

        tx.replace(R.id.frame_principal, fragmentEmpresa);
        tx.addToBackStack(null);
        tx.commit();
    }
}

MainFragmentListaCategorias:

package br.com.teste;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.List;

import br.com.teste.modelo.Categoria;
import br.com.teste.modelo.Cidade;
import br.com.teste.scripts.BuscaListaCategoriasTASK;

public class MainFragmentListaCategorias extends Fragment {
    private String idCidade;
    private View view;
    private Context context;
    private ListView lista;

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_main_lista_categorias, container, false);
        context = view.getContext();
        lista = (ListView)  view.findViewById(R.id.main_lista_categorias_list);

       Bundle params = getArguments();
        final Cidade cidade = (Cidade) params.getSerializable("cidade");
        idCidade = cidade.getId();

       lista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
               Categoria categoria = (Categoria) parent.getItemAtPosition(position);

                MainActivity mainActivity = (MainActivity) getActivity();
                mainActivity.carregaCategoria(cidade, categoria);
            }
        });

         new BuscaListaCategoriasTASK(this, idCidade).execute();

        return view;
    }

    public void onResume() {
        super.onResume();
    }

    public void populaList(List<Categoria> categorias) {
        ArrayAdapter adapterCategorias = new ArrayAdapter(context, android.R.layout.simple_list_item_1, categorias);
        lista.setAdapter(adapterCategorias);
    }
}

BuscaListaCategoriasTASK:

package br.com.teste.scripts;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import br.com.teste.MainFragmentListaCategorias;
import br.com.teste.converter.CidadeConverter;
import br.com.teste.modelo.Categoria;
import br.com.teste.receiver.WebClientBuscaCategorias;

public class BuscaListaCategoriasTASK extends AsyncTask<Void, Void, String> {
    private final String idCidade;
    private MainFragmentListaCategorias fragmentCategorias;
    private ProgressDialog dialog;
    private Context context;

    public BuscaListaCategoriasTASK(MainFragmentListaCategorias fragmentCategorias, String idCidade){
        this.fragmentCategorias = fragmentCategorias;
        this.idCidade = idCidade;
        this.context = fragmentCategorias.getContext();
    }

    protected void onPreExecute() {
        dialog = ProgressDialog.show(context, "","", true, true);
    }

    protected String doInBackground(Void... params) {
        CidadeConverter conversor = new CidadeConverter();
        String json = conversor.converteParaJSON(idCidade);

        WebClientBuscaCategorias client = new WebClientBuscaCategorias();
        String resposta = client.post(json);

        return resposta;
    }

    protected void onPostExecute(String resposta) {
        dialog.dismiss();

        try {
            JSONObject json = new JSONObject(resposta);
            JSONArray categoriasJSONArray = json.getJSONArray("categorias");
            List<Categoria> categoriasList = new ArrayList();

            for (int i = 0; i < categoriasJSONArray.length(); i++) {
                Categoria categoria = new Categoria();

                JSONObject categoriaJSONObject = categoriasJSONArray.getJSONObject(i);
                String idCategoria   = categoriaJSONObject.getString("id");
                String nomeCategoria = categoriaJSONObject.getString("nome");
                String qtdeCategoria = categoriaJSONObject.getString("quantidade");

                categoria.setId(idCategoria);
                categoria.setNome(nomeCategoria);
                categoria.setQtde(qtdeCategoria);

                categoriasList.add(categoria);
            }
            fragmentCategorias.populaList(categoriasList);

        } catch (JSONException e) {
            e.printStackTrace();
            Toast.makeText(context, "Erro ao carregar lista de categorias...", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
solução!

Olá Nicolas,

Parece que o problema está no código que está no onResume(...) da MainActivity. O onResume(...) é chamado sempre que a Activity é colocada em primeiro plano para que o usuário possa interagir com o seu aplicativo. Isso significa que ele vai ser chamado a primeira vez que o seu aplicativo for aberto. Nesse caso, faz sentido colocar o primeiro Fragment na tela para que ele possa escolher. Depois que ele fizer as seleções e abrir o navegador, o Android irá invocar os métodos onPause(...) e depois onStop(...) na MainActivity. Novamente, até aqui não temos nenhum problema. Quando fecharmos o navegador, a MainActivity deverá voltar para o primeiro plano e nesse caso o Android vai invocar os métodos onRestart(...), onStart(...) e onResume(...)! Se ele invoca novamente o onResume(...) ao retornar do navegador, qual vai ser o Fragment que vai ser sempre exibido? Vamos ver no código:

public class MainActivity extends AppCompatActivity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    protected void onResume() {
        super.onResume();
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction tx = manager.beginTransaction();
        MainFragmentListaCategorias fragmentListaCategorias = new MainFragmentListaCategorias();

        Intent intent = getIntent();
        Cidade cidade = (Cidade) intent.getSerializableExtra("cidade");

        Bundle params = new Bundle();
        params.putSerializable("cidade", cidade);
        fragmentListaCategorias.setArguments(params);

        tx.replace(R.id.frame_principal, fragmentListaCategorias);
        tx.commit();
    }

    // resto do código

}

Perceba que o Fragment que será exibido é o MainFragmentListaCategorias independente do Fragment que estava selecionando antes de abrir o navegador. Para corrigir esse comportamento, você pode mudar esse código do onResume(...) para o onCreate(...) pois você só quer mostrar esse Fragment quando a Activity for aberta a primeira vez. Para as demais vezes, você quer mostrar o mesmo Fragment que estava selecionado antes de sair da Activity e isso o próprio Android vai fazer pra gente.

Jeferson, muito obrigado pela ajuda.

Nem me liguei nos comportamentos. Havia colocado no onResume(...) justamente para sempre atualizar a lista de categorias, mas isso atrapalhou todo o resto.

Poderia me indicar algum material sobre esses métodos?

onPause(...), onResume(...), onStart(...) ???

Muito obrigado pela ajuda!!!

Olá Nicolas,

O material que eu recomendo é a própria documentação do Android que pode ser encontrada aqui:

https://developer.android.com/guide/components/activities.html

Aqui fica detalhado o que significa cada um desses métodos e quais são as transições possíveis entre eles na seção de ciclo de vida das activities.

Obrigado.