ListView with different layouts by lines, according to filtered value

0

I have a single table in the DB, which contains records with fields like: tipo, data, hora, cliente, historico

According to the value of tipo , the cliente field is mandatory, ie vazio .

To create a ListView , I need to have the fields it will display, but there will be cases where this cliente field, like others, will be empty.

Would I have to generate the records of ListView by displaying the fields specified by register according to their the tipo field, so to display only what is required by the record type?

Example:

If it is type = 1, it displays the fields:

  • TYPE - DATE - CLIENT

If it is type = 2, it displays the fields:

  • TYPE - TIME - HISTORICAL
asked by anonymous 30.01.2018 / 11:43

3 answers

4

Yes it is possible.

For this you should do / do:

  • A class that represents each item (Client) with "getters" for each of the values it wants to display.
  • A custom adapter .
  • A layout for each line type.

In the Adapter you have to override the methods

public int getViewTypeCount()

and

public int getItemViewType(int position)

The first should return the number of different views / layouts that will be created in getView() , second the view / layout current.

The getView() method of the Adapter should be implemented so that, based on the value returned by getItemViewType() , create the layout to use and fill in your views in> according to the values in the ArrayList (clients):

public class ClientesAdapter extends ArrayAdapter<Cliente> {

    private LayoutInflater inflater;
    private ArrayList<Cliente> Clientes;

    public ClientesAdapter(Context context, ArrayList<Cliente> clientes) {
        super(context, 0, clientes);
        this.clientes = clientes;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getViewTypeCount() {
      return 2;
    }

    @Override
    public int getItemViewType(int position) {
      return clientes.get(position).getTipo();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        int type = getItemViewType(position);

        if (v == null) {

            // Cria a view em função do tipo
            if (type == 1) {
                // Layout para o tipo 1
                v = inflater.inflate(R.layout.layout_tipo1, parent, false);
        }
        else {
            // Layout para o tipo 2
            v = inflater.inflate(R.layout.layout_tipo2, parent, false);
        }

        //O cliente para esta linha
        Cliente cliente = clientes.get(position);

        if (type == 1) {
         // atribuir aqui os valores às views do layout_tipo1
        }else{
            // atribuir aqui os valores às views do layout_tipo2
        }

        return v;
    }
}  

The adapter is used like this:

ListView listView = (ListView) findViewById(R.id.clientes_list);
ArrayList<Clientes> clientes = getClientes(); 

ClientesAdapter clientesAdapter = new ClientesAdapter(this, clientes);
listView.setAdapter(clientesAdapter);

You will have to adapt it according to your needs.

    
30.01.2018 / 15:17
2

In fact we just need to subscribe to the getView method of the ArrayAdapter. Perhaps with this example the idea of controlling the views you want to display in a ListView via an array adapter is simpler.

public class MyAdapter extends ArrayAdapter<MyObject>
{

    public MyAdapter(Context context, ArrayList<MyObject> myObjects){
        super(context, 0, myObjects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {

        if(convertView == null){
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.my_list_item, parent, false);
        }

               //Recupera o Objecto da lista através do método getItem
        MyObject myObject = getItem(position);

                ((TextView) convertView).findViewById(R.id.text_view_one);

                ((TextView) convertView).findViewById(R.id.text_view_two);

               //Inteiro vindo da base de dados
              int tipo = myObject.getTipo();

                If(tipo == 1){
                    textView1.setText(....);

                    //Esconde a text view
                    textView2.setVisibility(View.GONE);
               }else{
                    textView1.setText(....);
                    textView2.setText(....);
           }
        return convertView;
    }
}
    
31.01.2018 / 07:28
0

I needed an adapter that would give me the following: now, at my choice, select a specific layout for when I get messages, sometimes a specific layout for when I send the message. After much time breaking my head I had this insight:

package adapters;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.stevenilson.appchat.R;

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

import objetos.Message;

public class MessageAdapter extends BaseAdapter {

List<Message> messages = new ArrayList<Message>();
Context context;
public MessageAdapter(Context context) {
    this.context = context;
}
public void add(Message message) {
    this.messages.add(message);
    notifyDataSetChanged();
}
@Override
public int getCount() {
    return messages.size();
}
@Override
public Object getItem(int i) {
    return messages.get(i);
}
@Override
public long getItemId(int i) {
    return i;
}
@Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
    MessageViewHolder holder = new MessageViewHolder();
    LayoutInflater messageInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    Message message = messages.get(i);
    if (message.isBelongsToCurrentUser()) {
        convertView = messageInflater.inflate(R.layout.my_message, null);
        holder.messageBody = (TextView) convertView.findViewById(R.id.message_body);
        convertView.setTag(holder);
        holder.messageBody.setText(message.getText());
    } else {
        convertView = messageInflater.inflate(R.layout.their_message, null);
        holder.avatar = (View) convertView.findViewById(R.id.avatar);
        holder.name = (TextView) convertView.findViewById(R.id.name);
        holder.messageBody = (TextView) convertView.findViewById(R.id.message_body);
        convertView.setTag(holder);
        holder.name.setText(message.getData().getName());
        holder.messageBody.setText(message.getText());
        GradientDrawable drawable = (GradientDrawable) holder.avatar.getBackground();
        drawable.setColor(Color.parseColor(message.getData().getColor()));
    }
    return convertView;
}
}

class MessageViewHolder {
    public View avatar;
    public TextView name;
    public TextView messageBody;
}

Using this adapter together with a Message object for the other attributes:

package objetos;

import com.stevenilson.appchat.ChatMessage;

public class Message {
    private String text;
    private ChatMessage data;
    private boolean belongsToCurrentUser;
    public Message(String text, ChatMessage data, boolean belongsToCurrentUser) {
        this.text = text;
        this.data = data;
        this.belongsToCurrentUser = belongsToCurrentUser;
    }
    public String getText() {
        return text;
    }
    public ChatMessage getData() {
        return data;
    }
    public boolean isBelongsToCurrentUser() {
        return belongsToCurrentUser;
    }
}

With this I instantiate both in my main and in each method ( sendMessage or receive ) I only changed boolean belongsToCurrentUser to the adapter to have control over what to do

sendMessage(View view){
    String texto = textMessage.getText().toString();


    belongsToCurrentUser = true;
    this.message.setText(texto);
    Message obMessage = new Message(texto, this.message, belongsToCurrentUser);


    if (texto.length() > 0) {

        messageAdapter.add(obMessage);
        this.message.setAction(ChatMessage.Action.SEND_ALL);
        this.message.setText(texto);
        this.socketTask.send(this.message);

    }

    listView.setSelection(listView.getCount() - 1);
}

I think that later, this answer might help somebody.

    
10.11.2018 / 01:37