How to use an array within getView on an Adapter?

Asked

Viewed 140 times

1

Here’s my problem, I’m passing a sequence of arrays to an Adapter that should be placed inside a listview, among these I have a two-dimensional array called materials :

public View onCreateView(...){
...
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // Meus arrays que vão dentro do array bidimensional
    int[] mat1 = new int[]{R.drawable.bronze};
    int[] mat2 = new int[]{R.drawable.prata};
    int[] mat3 = new int[]{R.drawable.ouro};

    int[] imagens = new int[]{R.drawable.adaga, R.drawable.espada, R.drawable.machado};
    String[] nomes = new String[]{"Adaga", "Espada", "Machado"};
    int[][] materiais = new int[][]{mat1, mat2, mat3}; // Meu array bidimensional.
    String[] desc = new String[]{"Uma adaga", "Uma espada", "Um machado"};
    int[] cores = getActivity().getResources().getIntArray(R.array.cores);

    ListView listView = (ListView) getActivity().findViewById(R.id.menuFerreiroMateriaisListView);
    listView.setAdapter(new FragFerreiroArrayAdapter(getActivity(), imagens, nomes, materiais, desc, cores));

    super.onActivityCreated(savedInstanceState);
}

The custom Adapter that receives the arrays is this, the idea is to create a list of items (in my case, a dagger, a sword and an axe), where each one has a name, an image, a description and a list of icons that would be the materials used to create that item:

public class FragFerreiroArrayAdapter extends BaseAdapter {

private final String TAG = "FragFerreiro";

private final List<Item> mItems = new ArrayList<Item>();
private final LayoutInflater mInflater;
private final Context context;

// Este é o construtor chamado que recebe o array bidimensional da class anterior
public FragFerreiroArrayAdapter(Context context, int[] imagens, String[] nomes, int[][] materiais, String[] desc, int[] cores) {
    this.context = context;
    mInflater = LayoutInflater.from(this.context);

    //int[] teste = new int[] {R.drawable.bronze};

    // Aqui eu crio um novo objeto item que vai ser
    // referente a uma linha dentro do meu layout,
    // repare que ele recebe o valor de array materiais[]
    // que é na verdade um array de int definido na classe
    // anterior.
    for (int i = 0; i < imagens.length; i++) {
        mItems.add(new Item(imagens[i], nomes[i], materiais[i], desc[i], cores[i]));
        //mItems.add(new Item(imagens[i], nomes[i], teste, desc[i], cores[i]));
    }

}

@Override
public int getCount() {
    return mItems.size();
}

@Override
public Item getItem(int i) {
    return mItems.get(i);
}

@Override
public long getItemId(int i) {
    // TODO verificar esse mêtodo
    return mItems.get(i).imagem;
}

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    View v = view;
    ImageView imagemItem;
    TextView nomeItem;
    LinearLayout materiaisItem;
    TextView descricaoItem;

    if (v == null) {
        v = mInflater.inflate(R.layout.menu_ferreiro_frag_materiais_item_imagem, viewGroup, false);
        v.setTag(R.id.menu_ferreiro_frag_materiais_item_imagem, v.findViewById(R.id.menu_ferreiro_frag_materiais_item_imagem));
        v.setTag(R.id.menu_ferreiro_frag_materiais_item_nome, v.findViewById(R.id.menu_ferreiro_frag_materiais_item_nome));
        v.setTag(R.id.menu_ferreiro_frag_materiais_item_materiais_necessarios, v.findViewById(R.id.menu_ferreiro_frag_materiais_item_materiais_necessarios));
        v.setTag(R.id.menu_ferreiro_frag_materiais_item_descricao, v.findViewById(R.id.menu_ferreiro_frag_materiais_item_descricao));
    }

    Item itemAtual = getItem(i);

    imagemItem = (ImageView) v.getTag(R.id.menu_ferreiro_frag_materiais_item_imagem);
    imagemItem.setImageResource(itemAtual.imagem);

    nomeItem = (TextView) v.getTag(R.id.menu_ferreiro_frag_materiais_item_nome);
    nomeItem.setText(itemAtual.nome);

    // Este é um linear layout envolvido em um horizontal scroll view que deve receber uma lista de ícones.
    materiaisItem = (LinearLayout) v.getTag(R.id.menu_ferreiro_frag_materiais_item_materiais_necessarios);

    // Esta parte do código está dando MUITA dor de cabeça.
    for(int e=0;e<itemAtual.materiais.length;e++)
    {
        ImageView imagem = new ImageView(context);
        imagem.setImageResource(itemAtual.materiais[e]);
        materiaisItem.addView(imagem);
    }

    descricaoItem = (TextView) v.getTag(R.id.menu_ferreiro_frag_materiais_item_descricao);
    descricaoItem.setText(itemAtual.descricao);

    // TODO adicionar cor de fundo

    return v;
}

private static class Item {
    public final int imagem;
    public final String nome;
    int[] materiais;
    public final String descricao;
    public final int cor;
    private final String TAG = "Item";

    Item(int imagem, String nome, int[] materiais, String descricao, int cor) {
        this.imagem = imagem;
        this.nome = nome;
        this.materiais = materiais;
        this.descricao = descricao;
        this.cor = cor;
    }
}
}

The list is created correctly as expected and the lines are added correctly:

linhas criadas

However, in this part of the code, for some reason it defines the first line with all the icons passed by the material array as can be seen above, where there should be only one image of a "copper", there are 2 pictures of copper and more 1 of silver and another of gold:

    for(int e=0;e<itemAtual.materiais.length;e++)
    {
        ImageView imagem = new ImageView(context);
        imagem.setImageResource(itemAtual.materiais[e]);
        materiaisItem.addView(imagem);
    }

I have already tried to verify the origin of the problem by placing text outputs for the log in each step by counting the values of the array and printing them. I’m really out of ideas, I did this little project exactly to learn how to use custom Adapters but by the looks of it, I stopped at a very silly mistake and I can’t solve.

This is the XML of the item created in custom Adapter:

<ImageView
    android:id="@+id/menu_ferreiro_frag_materiais_item_imagem"
    android:layout_width="100sp"
    android:layout_height="100sp"
    android:clickable="false" />

<RelativeLayout
    android:id="@+id/menu_ferreiro_frag_materiais_item_conteudo_interno"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignBottom="@+id/menu_ferreiro_frag_materiais_item_imagem"
    android:layout_alignParentTop="true"
    android:layout_toEndOf="@+id/menu_ferreiro_frag_materiais_item_imagem"
    android:layout_toRightOf="@+id/menu_ferreiro_frag_materiais_item_imagem"
    android:clickable="false"
    android:orientation="vertical">

    <TextView
        android:id="@+id/menu_ferreiro_frag_materiais_item_nome"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/menu_ferreiro_frag_materiais_item_descricao"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/menu_ferreiro_frag_materiais_item_nome"
        android:clickable="false"
        android:textSize="20sp"
        />

    <HorizontalScrollView
        android:layout_below="@id/menu_ferreiro_frag_materiais_item_descricao"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <LinearLayout
            android:id="@+id/menu_ferreiro_frag_materiais_item_materiais_necessarios"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"/>

    </HorizontalScrollView>

</RelativeLayout>

<Button
    android:id="@+id/menu_ferreiro_frag_materiais_item_botao_criar"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_alignEnd="@+id/menu_ferreiro_frag_materiais_item_conteudo_interno"
    android:layout_alignParentTop="true"
    android:layout_alignRight="@+id/menu_ferreiro_frag_materiais_item_conteudo_interno"
    android:text="Criar" />

  • I think it would be more interesting to use Expandable list view fits perfectly in your approach

  • Caíque, the idea is one item per list without changing the size, but I’ll take a look to see if I can use Expandable list.

1 answer

0


OK,

discovered the problem, as it is possible to notice by all used methods this class is a Fragment that is inflated in an Activity:

public View onCreateView(...){
...
}

@Override
public void onActivityCreated(...) {
...
}

This is the activity that receives the above class, note that it has as the view the menu_ferreiro_activity:

public class MenuFerreiro extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.menu_ferreiro_atividade);
        .
        .
        .
    }
}

This is the XML in question, it has a framelayout used only to be replaced by the user-selected fragment:

<LinearLayout
    ...>

    <Button
        ... />

    <Button
        ... />

    <Button
       ... />

</LinearLayout>

<FrameLayout
    android:id="@+id/menuFerreiroFrameLayout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

</LinearLayout>

It seems to me that because I was using "wrap_content" the fragment was being rendered 2 times because the application did not have the exact screen size, which caused all the images to be placed on the first line in the first rendering and only then had the execution done as expected. I switched from "wrap_content" to "fill_parent" and the screen started to be rendered only once, resulting in the screen:

Imagem correta

Summary: When using getView on an adapter, remember that it will be called more than once if the parent view of the view you are moving has the layout_height and layout_width as wrap_content, What really counts is the main view and not necessarily the view that gets what you’re wanting to inflate.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.