JannGabriel
JannGabriel

Reputation: 302

Android Listview reset changes when scroll

I'm using a ListFragment with a custom Adapter.

My adapter have a textview and a hide imageview with a arrow. When user select a item, the arrows shows up and the background color change. But, when user scroll the list, all the changes get back to default.

What I should do to fix the changes?

EDIT:

my Adapter class..

public class PropriedadeAdapter extends BaseAdapter {
private Context context;
private List<Propriedades> prop;

public PropriedadeAdapter(Context context, List<Propriedades> prop) {
    this.context = context;
    this.prop = prop;
}

public int getCount() {
    return prop.size();
}

public Object getItem(int position) {
    return prop.get(position);
}

public long getItemId(int position) {
    return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
    // Recupera o produto da posição atual
    Propriedades p = prop.get(position);

    // Layout XML
    int arquivoLayout = R.layout.lista_prop;
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = inflater.inflate(arquivoLayout, null);

    // Atualiza o valor do Text para o nome do produto
    TextView textNome = (TextView) v.findViewById(R.id.nome);
    textNome.setText(p.getNome());

    return v;
}
}

my Fragment class..

public class frag_lista extends ListFragment{

ImageView ultimoItem = null;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
     ArrayList<Propriedades> props = new ArrayList<Propriedades>();
    for(int i = 0; i <50; i++)
    {
        Propriedades prop = new Propriedades();
        prop.setNome("FRUTA "+i);
        props.add(prop);
    }
    setListAdapter(new PropriedadeAdapter(this.getActivity(),props));
}


@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    ImageView seta = (ImageView)v.findViewById(R.id.imgSeta);
    seta.setVisibility(0);
    LinearLayout linha = (LinearLayout)v.findViewById(R.id.linha);
    linha.setBackgroundColor(Color.GRAY);
    if(ultimoItem != null)
    {
        ultimoItem.setVisibility(4);
    }
    ultimoItem = seta;
}   

}

what i should do to persiste the changes of onListItemClick method????

Upvotes: 1

Views: 2881

Answers (2)

Gayashan Perera
Gayashan Perera

Reputation: 21

convertView has two states where it is null and not null. Your issue happens because eveytime yout getView() calls a new layout inflater instance is initializing. Initialize the inflater only when the convertView is null.

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

    Propriedades p = prop.get(position); 
    int arquivoLayout = R.layout.lista_prop;

    View v;

    if (convertView==null){
        v = inflater.inflate(arquivoLayout, null);
    }
    else {
        v = convertView;
    }  

    // Atualiza o valor do Text para o nome do produto
    TextView textNome = (TextView) v.findViewById(R.id.nome);
    textNome.setText(p.getNome());

    return v;
}

Also, remember to declare inflater as a field.

LayoutInflater inflater = null;

And to initialize it in the constructor.

public PropriedadeAdapter(Context context, List<Propriedades> prop) {
    this.context = context;
    this.prop = prop;
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

Upvotes: 2

Sly
Sly

Reputation: 2101

According to your comment, I think you don't use the Adapter correctly.

An Adapter provides methods that are automatically called by the ListView.

You should keep selected indexes in memory and restore the View state each time the getView(...) method is called (jusging from the position argument).

Look for tutorial about ListView and Adapter.

EDIT:

Note that I have not test the code but it could be something like this:

// TeddyBearFr: Class name typically starts with a capital letter! Frag_lista, not frag_lista
public class frag_lista extends ListFragment{

    ImageView ultimoItem = null;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
         ArrayList<Propriedades> props = new ArrayList<Propriedades>();
        for(int i = 0; i <50; i++)
        {
            Propriedades prop = new Propriedades();
            prop.setNome("FRUTA "+i);
            props.add(prop);
        }
        setListAdapter(new PropriedadeAdapter(this.getActivity(),props));
    }


    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {

        // TeddyBearFr: notify the adapter
        ( (PropriedadeAdapter) this.getListAdapter() ).onListItemClick(position);

        // TeddyBearFr: your last item must be managed in the getView(...) method of the Adapter
        //if(ultimoItem != null)
        //{
        //  ultimoItem.setVisibility(4);    // TeddyBearFr: don't use integer like this, use Android constants! View.INVISIBLE
        //}
        //ultimoItem = seta;
    }   

}


public class PropriedadeAdapter extends BaseAdapter {
    private final static String TAG = "PropriedadeAdapter";
    private Context context;
    private List<Propriedades> prop;
    private Set<Integer> mSelectedItemsPosition;

    public PropriedadeAdapter(Context context, List<Propriedades> prop) {
        this.context = context;
        this.prop = prop;
        // TeddyBearFr: set to store selected indexes
        this.mSelectedItemsPosition = new HashSet<Integer>();
    }

    public int getCount() {
        return prop.size();
    }

    public Object getItem(int position) {
        return prop.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        Log.d(TAG, "getView(position=" + position + ", convertView=" + convertView + ", parent=" + parent + ")" );

        // Recupera o produto da posição atual
        Propriedades p = prop.get(position);

        // TeddyBearFr: use existing view if exist ; otherwise create a new one
        View v;
        if( convertView == null ){
            // Layout XML
            int arquivoLayout = R.layout.lista_prop;
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(arquivoLayout, null);
        }
        else{
            v = convertView;
        }

        // Atualiza o valor do Text para o nome do produto
        TextView textNome = (TextView) v.findViewById(R.id.nome);
        textNome.setText(p.getNome());

        // TeddyBearFr: update view according its selection state
        ImageView seta = (ImageView)v.findViewById(R.id.imgSeta);
        boolean isViewSelected = this.mSelectedItemsPosition.contains(position);
        int visibility = ( isViewSelected ? VIEW.VISIBLE : VIEW.GONE );
        seta.setVisibility(visibility);

        LinearLayout linha = (LinearLayout)v.findViewById(R.id.linha);
        linha.setBackgroundColor( isViewSelected ? Color.GRAY : Color.RED );

        if( position == getCount()-1 ){
            // perform special processes on the last item of the list if needed
        }

        return v;
    }

    // TeddyBearFr: callback when click
    public void onListItemClick(int position){
        Log.d(TAG, "onListItemClick(position=" + position + ")");

        // update selected index data
        // Note that I haven't tested if it works. Because native integer "position" will be wrapped in Integer object, there's a chance that the Set compares the references on objects instead of their value
        if( this.mSelectedItemsPosition.contains(position) ){
            this.mSelectedItemsPosition.remove(position);
        }
        else{
            this.mSelectedItemsPosition.add(position);
        }

        // ask the list to be refreshed -> you'll see that getView() will be called only for each displayed view
        this.notifyDataSetChanged();
    }

}

Upvotes: 0

Related Questions