Pegar item de ListView e mostrar em campo de outra tela

30 respostas
F

Boa noite meus amigos,

Estou com o seguinte problema:

Tenho uma classe que se chama BuscaCliente e nela tem uma lista. Quero clicar num item da lista e mandar para outra tela o nome e id. A tela chama CarrosCliente. O código abaixo chama a tela ao clicar, mas manda os dados em branco.

// Clicar em item da lista e mostra nos campos da tela de cadastro
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
    	super.onListItemClick(l, v, position, id);
		Intent intent = new Intent(this, CarrosCliente.class);
		intent.putExtra(DbAdapter.KEY_ID, id);
		startActivity(intent);
//		startActivityForResult(intent, 1);
    }

Obrigado.

30 Respostas

wagnerfrancisco

Por que você tá chamando startActivity duas vezes? Ou chama o startActivity, ou chama o startActivityForResult.

Você imprimiu os valores do id no método pra garantir que está sendo enviado?

Como está pegando estes valores na activity que os recebe?

F

Ta duplicado, colei errado. Mas como faria isso, não sei como fazer…

O correto seria:

// Clicar em item da lista e mostra nos campos da tela de cadastro
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
    	super.onListItemClick(l, v, position, id);
		Intent intent = new Intent(this, CarrosCliente.class);
		intent.putExtra(DbAdapter.KEY_ID, id);
		startActivityForResult(intent, 1);
    }

E coloquei esse código também:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    	super.onActivityResult(requestCode, resultCode, data);
    	if(requestCode == 1 && resultCode == RESULT_OK)
    		carregarLista();
    }

Tenho a tela BuscaCliente e a tela CarrosCliente. Eu clico no item da lista, chama a tela CarrosCliente mas não mostra no campo nome o dado clicado.

wagnerfrancisco

Use a classe android.util.Log. Ela vai imprimir no LogCat (se você estiver usando eclipse). Um exemplo simples:

@Override
   protected void onListItemClick(ListView l, View v, int position, long id) {
      super.onListItemClick(l, v, position, id);
      Log.d("BuscaCliente", String.valueOf(id)); // fazendo log

      Intent intent = new Intent(this, CarrosCliente.class);
      intent.putExtra(DbAdapter.KEY_ID, id);
      startActivityForResult(intent, 1);
   }

Poste onde você está recebendo estes valores também (e debugue lá tb!).

F

Como testo isso, é só rodar normalmente?

wagnerfrancisco

Sim. Você tá usando eclipse com o plugin ADT? Os logs serão exibidos numa aba chamada LogCat. Se ela não estiver aparecendo, aperte Ctrl + 3 e digite LogCat.

E poste o código onde você recebe o id na classe CarrosCliente pra nós vermos também!

F

Ta pegando o id, rodei e apareceu no rodapé do eclipse.

wagnerfrancisco

Se está pegando corretamente, seu problema é na hora de jogar este id na tela. Posta o código pra vermos melhor. E lembre-se que você está passando apenas o id (e não o nome, como vc mencionou no início), talvez este seja o problema.

F

Na outra classe:

private long mId;

mId = getIntent().getLongExtra(DbAdapter.KEY_ID, 0);

if(mId > 0){
			mDb.open();
			Cursor cliente = mDb.getCliente(mId);
			if(cliente.moveToFirst()){
				nome.setText(cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_NOME)));
				endereco.setText(cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_ENDERECO)));
				telefone.setText(cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_TELEFONE)));
				celular.setText(cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_CELULAR)));
				cpf.setText(cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_CPF)));
			}
			mDb.close();
		}
wagnerfrancisco

Nesta classe aí você imprimiu o mId também pra ver se chegou?

Se ele chegou corretamente, seu erro é na hora de passar este valor para a tela. Qual o código que você usa pra fazer isto?

F

Vou testar agora, um momento e ja posto.

F

Fiz assim na classe CarrosCliente:

public class CarrosCliente extends Activity{

private long mId;


mId = getIntent().getLongExtra(DbAdapter.KEY_ID, 0);
		
IdNome = (TextView) findViewById(R.id.IdNome);

mDb.open();
		
Cursor cliente = mDb.getCliente(mId);
		
  if(mId > 0){
    IdNome.setText(" "+cliente.getString(cliente.getColumnIndex("_id")));
  }  
		
} Aqui fecha a Activity

Agora nem chama mais a tela da erro ao clicar no item da lista na tela anterior.

wagnerfrancisco

Esse código que você colou está em qual método? Se não for muito grande, coloca a classe inteira.

F

Fiz assim na classe CarrosCliente, onde é pra aparecer os dados da tela anterior.

F

Classe BuscaClientes:

package br.com.oficinavittorazo;

import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class BuscaClientes extends ListActivity{
	public ImageButton voltar;
	public DbAdapter db;
	private EditText Procurar;

	
	@Override
	protected void onCreate(Bundle icicle){ // Início do método onCreate
		super.onCreate(icicle);
		setContentView(R.layout.busca_cliente_layout);

		db = new DbAdapter(this);
		db.open();

		Cursor clientes = db.getTodosClientes();
        clientes.moveToFirst();

		Procurar = (EditText) findViewById(R.id.etProcurar);
		Procurar.requestFocus();
		
		
		carregarLista();
		
		Procurar.addTextChangedListener(new TextWatcher() {
			
			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
				 CarregarEncontrados();
				//Carrega o listview com os itens encontrados
                lv.setAdapter(new ArrayAdapter<String>(CadastrarCarros.this, android.R.layout.simple_list_item_1, agenda_Encontrados)); */
				carregarLista();
			}
			
			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void afterTextChanged(Editable s) {
				// TODO Auto-generated method stub

			}
		});
		
		voltar = (ImageButton) findViewById(R.id.bt_voltar);
		
		voltar.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//  Evento ao clicar no botão Voltar
				setResult(RESULT_CANCELED);
				// Fecha a tela de Cadastro e Volta para a Principal
				finish();
			}
		});
	}
	
	
    // Clicar em item da lista e mostra nos campos da tela de cadastro
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
    	super.onListItemClick(l, v, position, id);
    	Log.d("BuscaCliente", String.valueOf(id)); // fazendo log
		Intent intent = new Intent(this, CarrosCliente.class);
		intent.putExtra(DbAdapter.KEY_ID, id);
		startActivityForResult(intent, 1);
    }

	private void carregarLista(){
		String nomeString = Procurar.getText().toString();
		db.open();
 //   	Cursor clientes = db.getTodosClientes();
		Cursor clientes = db.getClientePorNome(nomeString);
 
		clientes.moveToFirst();
        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.two_line_list_item, clientes, new String[] {DbAdapter.KEY_NOME, DbAdapter.KEY_ID}, new int[] {android.R.id.text1, android.R.id.text2});
		setListAdapter(adapter);
		
        db.close();
		// Setar lista na mão
		//String[] items = new String[] {"Carro", "Trabalho", "Faculdade"};
		//ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, items);
    }
	
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    	super.onActivityResult(requestCode, resultCode, data);
    	if(requestCode == 1 && resultCode == RESULT_OK)
    		carregarLista();
    } 
}

Classe CarrosCliente:

package br.com.oficinavittorazo;

import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.EditText;
import android.widget.ListView;
//import android.widget.ImageButton;
import android.widget.TextView;

public class CarrosCliente extends Activity{
	private long mId;
	private TextView IdNome;
//	private EditText nome;
//	private ImageButton salvar, pesquisar, limpar, voltar;

	
	private DbAdapter mDb;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.cadastro_carros_cliente_layout);
		
		mDb = new DbAdapter(this);
		
		mId = getIntent().getLongExtra(DbAdapter.KEY_ID, 0);
		
		IdNome = (TextView) findViewById(R.id.IdNome);
//		nome = (EditText) findViewById(R.id.editText_nome);
		
		mDb.open();
		
		Cursor cliente = mDb.getCliente(mId);
		
		if(mId > 0){
		  IdNome.setText(" "+cliente.getString(cliente.getColumnIndex("_id")));
//		  nome.setText(cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_NOME)));
		}  
		
	}

}
wagnerfrancisco

Aparentemente este código esta correto. Para termos certeza, imprima o mId nestes dois lugares:

public class CarrosCliente extends Activity{
	private long mId;
	private TextView IdNome;
//	private EditText nome;
//	private ImageButton salvar, pesquisar, limpar, voltar;

	private DbAdapter mDb;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.cadastro_carros_cliente_layout);
		
		mDb = new DbAdapter(this);
		
		mId = getIntent().getLongExtra(DbAdapter.KEY_ID, 0);
                Log.d("CarrosCliente", "mId: " + mId); //aqui
		
		IdNome = (TextView) findViewById(R.id.IdNome);
//		nome = (EditText) findViewById(R.id.editText_nome);
		
		mDb.open();
		
		Cursor cliente = mDb.getCliente(mId);
		
		if(mId > 0){
		  IdNome.setText(" "+cliente.getString(cliente.getColumnIndex("_id")));
                  Log.d("CarrosCliente", "mId: " + mId); // e aqui
//		  nome.setText(cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_NOME)));
		}  
		
	}

}

Você comentou que estava dando algum erro. Quando dá erro aparece a exceção lá no LogCat, dá uma olhada lá pra ver o que tá acontecendo.

F

Acho que o erro é esse: 08-15 01:21:03.032: E/AndroidRuntime(1343): java.lang.RuntimeException: Unable to start activity ComponentInfo{br.com.oficinavittorazo/br.com.oficinavittorazo.CarrosCliente}: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1

O id ta pegando, mas ta dando erro quando vai abrir a tela da classe CarrosCliente.

wagnerfrancisco

Certo, veja que o problema é no cursor. Neste local:

IdNome.setText(" "+cliente.getString(cliente.getColumnIndex("_id")));

Provavelmente cliente.getColumnIndex("_id") está retornando -1. Você tem certeza que este campo ("_id") está no select? Cola o select que é chamado quando você faz mDb.getCliente pra nós vermos.

F

Tá assim:

public Cursor getCliente(long Id){
	return mDb.query(DATABASE_TABLE_CLIENTES, null, KEY_ID + "=" + Id, null, null, null, null);
}
wagnerfrancisco

No segundo parâmetro do método query você deveria estar passando um array com as colunas que quer trazer do banco. Eu vi lá no seu código inicial que vc tinha DbAdapter.KEY_NOME, DbAdapter.KEY_ENDERECO, etc. Neste parâmetro você deve passar um array com estes campos.

F

Como faz isso? Não entendi… Eu só quero o id e o nome.

wagnerfrancisco

Hum, passando null ele vai retornar todos os campos do banco, então não precisa alterar conforme eu falei no último post.

Lá na classe CarrosCliente, ao invés disto:

IdNome.setText(" "+cliente.getString(cliente.getColumnIndex("_id")));

Use isto:

IdNome.setText(" "+cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_ID)));

Se isto não resolver, só sabendo quais são as colunas da sua tabela no banco de dados pra resolver.

F

Deu erro ao clicar no item da lista:

08-15 01:41:39.021: E/AndroidRuntime(1426): java.lang.RuntimeException: Unable to start activity ComponentInfo{br.com.oficinavittorazo/br.com.oficinavittorazo.CarrosCliente}: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1

Dados da tabela:

private static final String DATABASE_TABLE_CLIENTES = "clientes";
	public static final String KEY_ID = "_id";
	public static final String KEY_NOME = "nome";
	public static final String KEY_ENDERECO = "endereco";
	public static final String KEY_TELEFONE = "telefone";
	public static final String KEY_CELULAR = "celular";
	public static final String KEY_CPF = "cpf";
	
	private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE_CLIENTES + " ("
		+ KEY_ID + " integer primary key autoincrement, "
		+ KEY_NOME + " text, "
		+ KEY_ENDERECO + " text, "
		+ KEY_TELEFONE + " text, "
		+ KEY_CELULAR + " text, "
		+ KEY_CPF + " text);";
F

Não sei se ajuda, mas o IdNome tá declarado assim:

private TextView IdNome;
wagnerfrancisco

humm, mas vc removeu o moveToFirst do cursor… tente assim:

if(mId > 0 && cliente.moveToFirst()){
   IdNome.setText(" "+cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_ID)));    
}
F

Legal, trouxe o id, agora to precisando do nome. Consegui com o nome, fiz a mesma coisa. Como deixar o EditText sem edição?

wagnerfrancisco

Ora, se para acessar o id você usou:

cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_ID));

Para acessar o nome basta trocar a chave pelo nome:

cliente.getString(cliente.getColumnIndex(DbAdapter.KEY_NOME));

E aí você decide onde colocar este valor (se vai concatenar com o id ou criar outro TextView.

F

VALEU Wagner,

Funcionou perfeito aqui. O que estava fazendo de errado? Como posso deixar o EditText sem edição, modo leitura?

F

Wagner, se quiser mais uma tabela é só fazer o mesmo da Tabela Clientes?

private static final String DATABASE_TABLE_CLIENTES = "clientes";
	public static final String KEY_ID = "_id";
	public static final String KEY_NOME = "nome";
	public static final String KEY_ENDERECO = "endereco";
	public static final String KEY_TELEFONE = "telefone";
	public static final String KEY_CELULAR = "celular";
	public static final String KEY_CPF = "cpf";
	
	private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE_CLIENTES + " ("
		+ KEY_ID + " integer primary key autoincrement, "
		+ KEY_NOME + " text, "
		+ KEY_ENDERECO + " text, "
		+ KEY_TELEFONE + " text, "
		+ KEY_CELULAR + " text, "
		+ KEY_CPF + " text);";

Para a tabela Carros faria o mesmo do código acima? E no caso do id do cliente, teria que ter na tabela Carros, ou seja os campos seriam esses:

IdCarro
IdCliente
Placa
Modelo

wagnerfrancisco

Cara, quanto ao campo ser não editável, eu não sei como tá isso nas versões atuais do Android, mas há um tempo atrás era uma droga, por que a propriedade editable não funcionava. Tem várias gambiarras pra fazer isso, eu usava essa:

<EditText ...
        android:clickable="false" 
        android:cursorVisible="false" 
        android:focusable="false" 
        android:focusableInTouchMode="false">
</EditText>

O procedimento para outras tabelas é semelhante. Recomendo que ao invés de ter apenas uma classe chamada DbAdapter, você tenha várias: ClienteDbAdapter, CarroDbAdapter, etc. Aí cada uma tem as suas informações.

F

Beleza, vou setar num TextView, ai não tem como editar. Seria igual o conteúdo somente mudando o nome da tabela? E onde cria o banco?

private static final String DATABASE_NAME = “oficina”;
private static final int DATABASE_VERSION = 1;

Igual pra todas as classes DbAdapter que criar?

Criado 14 de agosto de 2012
Ultima resposta 14 de ago. de 2012
Respostas 30
Participantes 2