1

I'm trying to change the FragmentList item background color after click on this item an confirm an AlertDialog that is shown, it works but it's changing others items beside the clicled item.... This is all my code below...

public class RefrigeranteFragment extends ListFragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

public View SelectedView;

String[] refrigerantes = new String[] {
        "Coca Cola",
        "Coca Cola Zero",
        "Fanta Uva",
        "Guaraná Antartica",
        "Guaraná Antartica Zero",
        "Sukita",
        "Sukita Laranja",
        "Sprite",
        "Guaraná Antartica",
        "Sukita Uva"
};

// Array of strings to store currencies
String[] precos = new String[]{
        "02,50",
        "03,00",
        "02,00",
        "04,50",
        "02,50",
        "03,45",
        "01,50",
        "03,90",
        "07,00",
        "04,50"
};

int[] icones = new int[]{
    R.drawable.ic_coca_lata,
    R.drawable.ic_coca_zero_lata,
    R.drawable.ic_fanta_uva_lata,
    R.drawable.ic_guarana_antartica_lata,
    R.drawable.ic_guarana_antartica_zero_lata,
    R.drawable.ic_sukita_uva_lata,
    R.drawable.ic_sukita_laranja_lata,
    R.drawable.ic_sprite_lata,
    R.drawable.ic_guarana_antartica_pet,
    R.drawable.ic_sukita_uva_pet
};

private OnFragmentInteractionListener mListener;

public RefrigeranteFragment() {
    // Required empty public constructor
}

// TODO: Rename and change types and number of parameters
public static RefrigeranteFragment newInstance(String param1, String param2) {
    RefrigeranteFragment fragment = new RefrigeranteFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    List<HashMap<String, String>> aList = new ArrayList<HashMap<String, String>>();

    for (int i = 0; i < 10; i++){
        HashMap<String, String> hm = new HashMap<String, String>();
        hm.put("txtNome", refrigerantes[i]);
        hm.put("txtPreco", precos[i]);
        hm.put("img_refrigerante", Integer.toString(icones[i]));
        aList.add(hm);
    }

    String[] from = {"img_refrigerante", "txtNome", "txtPreco"};
    int[] to = {R.id.img_refrigerante, R.id.txtNome, R.id.txtPreco};

    SimpleAdapter adapter = new SimpleAdapter(getActivity().getBaseContext(), aList, R.layout.listview_refrigerante_layout, from, to);
    setListAdapter(adapter);
    // Inflate the layout for this fragment
    return super.onCreateView(inflater, container, savedInstanceState);
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

@Override
public void onListItemClick(ListView listView, View view, int position, long id){
    super.onListItemClick(listView, view, position, id);

    final View v = view;

    final TextView txt = (TextView)view.findViewById(R.id.txtNome);
    final ImageView imageView = (ImageView)view.findViewById(R.id.img_refrigerante);
    final TextView tvQuantity = (TextView)view.findViewById(R.id.txtQtde);
    final TextView lblQuantity = (TextView)view.findViewById(R.id.lblQtde);
    final NumberPicker txtQtde = new NumberPicker(getContext());

    txtQtde.setMinValue(1);
    txtQtde.setMaxValue(10);

    if(tvQuantity.getText() != "")
        txtQtde.setValue(Integer.parseInt(tvQuantity.getText().toString()));

    AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
    builder.setTitle(txt.getText());
    builder.setMessage("Informe a quantidade");
    builder.setIcon(imageView.getDrawable());

    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.MATCH_PARENT,
            LinearLayout.LayoutParams.MATCH_PARENT);

    txtQtde.setLayoutParams(lp);

    builder.setView(txtQtde);

    builder.setPositiveButton("Ok",
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {

                    tvQuantity.setText(String.valueOf(txtQtde.getValue()));
                    tvQuantity.setVisibility(View.VISIBLE);
                    lblQuantity.setVisibility(View.VISIBLE);

                    v.setBackgroundColor(Color.parseColor("#FF9933"));

                    ((TextView)v.findViewById(R.id.lblNome)).setTextColor(Color.WHITE);
                    ((TextView)v.findViewById(R.id.txtNome)).setTextColor(Color.WHITE);
                    ((TextView)v.findViewById(R.id.lblPreco)).setTextColor(Color.WHITE);
                    ((TextView)v.findViewById(R.id.txtPreco)).setTextColor(Color.WHITE);
                    ((TextView)v.findViewById(R.id.lblQtde)).setTextColor(Color.WHITE);
                    ((TextView)v.findViewById(R.id.txtQtde)).setTextColor(Color.WHITE);
                }

            });

    builder.setNegativeButton("Cancelar",
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            }
    );

    builder.show();

}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}

}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:paddingLeft="8dp"
    android:paddingRight="8dp">

    <ImageView
        android:id="@+id/img_refrigerante"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/pizza_fragment"
        android:paddingRight="10dp"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:src="@drawable/ic_menu_pizza2" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_below="@+id/img_refrigerante" >

        <TextView
            android:id="@+id/lblNome"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Refrigerante: "
            android:textStyle="bold"
            android:textSize="15dp"
            android:layout_below="@id/img_pizza" />

        <TextView
            android:id="@+id/txtNome"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15dp"
            android:layout_toRightOf="@+id/lblNome" />

        <TextView
            android:id="@+id/lblPreco"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Preço: "
            android:textStyle="bold"
            android:textSize="15dp"
            android:layout_below="@+id/txtNome" />

        <TextView
            android:id="@+id/txtPreco"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15dp"
            android:layout_toRightOf="@+id/lblPreco"
            android:layout_below="@+id/txtNome" />

        <TextView
            android:id="@+id/lblQtde"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Qtde.: "
            android:textStyle="bold"
            android:textSize="15dp"
            android:visibility="invisible"
            android:layout_below="@+id/txtPreco" />

        <TextView
            android:id="@+id/txtQtde"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15dp"
            android:visibility="invisible"
            android:layout_toRightOf="@+id/lblQtde"
            android:layout_below="@+id/txtPreco" />

    </RelativeLayout>

</RelativeLayout>
Junior Silva
  • 387
  • 5
  • 17

2 Answers2

0

That is happening because of view recycling within ListView.

In order for this to work, you need three things:

  • You need variables in your adapter that stores the "clicked" state of the items; for example, a list of booleans.

  • In your onListItemClick(), you need to call a method on the adapter to change the state of the current item and call notifyDataSetChanged().

  • In your getView() override, you need to check this state and set the background of the view you are creating accordingly.


Here's code for an adapter (inner class for your activity) that remembers if an item has been clicked (and also the quantity):

    public static class MyListAdapter extends BaseAdapter {

        private String[] mNames;

        private String[] mPrices;

        private int[] mIcons;

        private int[] mQtys;

        private boolean[] mClicked;

        public MyListAdapter(String[] names, String[] prices, int[] icons) {
            mNames = names;
            mPrices = prices;
            mIcons = icons;
            mQtys = new int[names.length];
            mClicked = new boolean[names.length];
        }

        @Override
        public int getCount() {
            return mNames.length;
        }

        @Override
        public Object getItem(int position) {
            return mNames[position];
        }

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

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

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

            ImageView icon = (ImageView) convertView.findViewById(R.id.img_refrigerante);
            icon.setImageResource(mIcons[position]);

            TextView name = (TextView) convertView.findViewById(R.id.txtNome);
            name.setText(mNames[position]);

            TextView price = (TextView) convertView.findViewById(R.id.txtPreco);
            price.setText(mPrices[position]);

            // hide these if qty == 0
            TextView qty = (TextView) convertView.findViewById(R.id.txtQtde);
            qty.setText(mQtys[position]);
            qty.setVisibility(mQtys[position] == 0 ? View.INVISIBLE : View.VISIBLE);

            TextView qtyLbl = (TextView) convertView.findViewById(R.id.lblQtde);
            qtyLbl.setVisibility(mQtys[position] == 0 ? View.INVISIBLE : View.VISIBLE);

            // here is where we use the clicked flag to determine which colors to set
            // TODO put a real color for backgroundColorNormal because I don't know what your normal background color is
            int backgroundColor = mClicked[position] ? Color.parseColor("#FF9933") : backgroundColorNormal;
            convertView.setBackgroundColor(backgroundColor);

            // TODO put a real color for colorNormal because I don't know what your normal text color is
            int textColor = mClicked[position] ? Color.WHITE : colorNormal;
            ((TextView) convertView.findViewById(R.id.lblNome)).setTextColor(textColor);
            ((TextView) convertView.findViewById(R.id.txtNome)).setTextColor(textColor);
            ((TextView) convertView.findViewById(R.id.lblPreco)).setTextColor(textColor);
            ((TextView) convertView.findViewById(R.id.txtPreco)).setTextColor(textColor);
            ((TextView) convertView.findViewById(R.id.lblQtde)).setTextColor(textColor);
            ((TextView) convertView.findViewById(R.id.txtQtde)).setTextColor(textColor);

            return convertView;
        }

        public int getQty(int position) {
            return mQtys[position];
        }

        public void setQty(int position, int qty) {
            mQtys[position] = qty;
            notifyDataSetChanged();
        }

        public void setClicked(int position, boolean clicked) {
            mClicked[position] = clicked;
            notifyDataSetChanged();
        }
    }

When you change a click flag or quantity, notifyDataSetChanged() is called. This is what tells the ListView to ask the adapter again for item views through getView(), and the item views are updated using the new values.

You need to keep a reference to this adapter in your activity:

    private MyListAdapter mAdapter;

and set it up:

    mAdapter = new MyListAdapter(refrigerantes, precos, icones);
    setListAdapter(mAdapter);

then your item click handler would look like this (I simplified it a bit)

    @Override
    public void onListItemClick(ListView listView, View view, final int position, long id){
        super.onListItemClick(listView, view, position, id);

        final NumberPicker txtQtde = new NumberPicker(getContext());

        txtQtde.setMinValue(1);
        txtQtde.setMaxValue(10);
        txtQtde.setValue(Integer.parseInt(mAdapter.getQty(position)));

        AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
        builder.setTitle(refrigerantes[position]);
        builder.setMessage("Informe a quantidade");
        builder.setIcon(icones[position]);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT);

        txtQtde.setLayoutParams(lp);

        builder.setView(txtQtde);

        builder.setPositiveButton("Ok",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mAdapter.setQty(position, txtQtde.getValue());
                        mAdapter.setClicked(position);
                    }

                });

        builder.setNegativeButton("Cancelar",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.cancel();
                    }
                }
        );

        builder.show();

    }

Please -- do more than just copy/paste this and take the time to go through the code line by line to understand how it works. Looking at sample code is a good way to learn about Android, but you won't learn anything if you copy/paste without understanding.

kris larson
  • 30,387
  • 5
  • 62
  • 74
  • Thanks for you reply, but i'm really a beginner on android development, would you mind to explain me how to do that in details? I'd be very thankful! – Junior Silva Jan 21 '16 at 16:20
  • Hi, thanks for your reply! No, it happens whenever i click on an option, then it select some other options instead of only the clicked option... – Junior Silva Jan 21 '16 at 16:23
  • Views are "recycled" as you scroll in a `ListView` to avoid constant inflation/construction of views. So on user click you are setting the background color for a view, then this view is reused as the list is scrolled so you see the same background again on another item. You should post the code where the adapter is assigned to your list view, and if you have extended an adapter, you should post your adapter code as well. This will enable the SO community to help you more. – kris larson Jan 21 '16 at 17:38
  • Thanks Kris, i've updated my question... I appreciate your help! – Junior Silva Jan 21 '16 at 17:52
  • Also please post your listview_refrigerante_layout.xml. You made this list work with a `SimpleAdapter`, and now you have this background color change that is a little more complex than `SimpleAdapter` is meant to handle. I have to put this aside now and come back and look at it later, but until then you should do some research into `ArrayAdapter` and `BaseAdapter` classes and consider what it would take to make your list work by writing your own extension of these classes. – kris larson Jan 21 '16 at 18:56
  • Hi Kris! You're the guy! It worked like a charm.... Thanks a lot, and i'm going to analyse all the code in order to learn more about it... Thanks Again! – Junior Silva Jan 24 '16 at 09:18
0

In this link I showed how to change item background color in AlertDialog. It also shows how to customize the AletDialog. For example, how to change divider colro and etc. Please visit this link:

https://stackoverflow.com/a/33439849/5475941.

I hope it helps.

Community
  • 1
  • 1
Mohammad
  • 6,024
  • 3
  • 22
  • 30
  • Hi Mohammad! This was great!!! Thanks for one more help! It's good to have someone to help us who are beginners... – Junior Silva Feb 12 '16 at 01:06
  • You are very welcome buddy. We were all beginners once :) The most important thing is that we have tendency to learn. – Mohammad Feb 12 '16 at 03:43
  • That's right! do you have another channel where we can make you questions about android directly? Thanks again! – Junior Silva Feb 14 '16 at 10:53
  • Silva, I am active in Stack-overflow. It is a great community. If you ask a question here, my friends and I will answer it. I hope one day, you will answer other people's questions. However, if you ask any question about android you can notify me with this email: m_vahidalizadeh@live.com, then I will answer the question if I can :) – Mohammad Feb 15 '16 at 19:56
  • Oh thank you very much Mohammad... Could you help me on this: http://stackoverflow.com/questions/35398284/android-list-fragment-with-fixed-header – Junior Silva Feb 16 '16 at 16:59