TextView in listview rows showing repeated values on scroll in Android?
Asked Answered
S

3

7

I am working with custom Adapter of a ListView in which I have a TextView and a Spinner. After selecting the values from a Spinner, the value after copied to the TextView of the respective same Row of list.

Problem is, As I have more than 40 elements in the ListView , when I select the first spinner and set the value to the respective TextView, on scroll, the same value is seen in the 10th Row TextView.

Values are copied from 1st TextViewto 10th TextView on scroll.

Below is the code which I am using:

public class AppListAdapter extends BaseAdapter {

    private LayoutInflater mInflater;
    private List<App> mApps = Constants.list;
    private Context _activity;
    ArrayList<String> months=null;
    ArrayAdapter<String> dataAdapter =null;
    int spinerposition;
    int viewposition;

    int temp=0;
    private int screenWidth;


    /**
     * Constructor.
     * 
     * @param context the application context which is needed for the layout inflater
     * @param screenWidth 
     */
    public AppListAdapter(Context context, int screenWidth) {
        // Cache the LayoutInflate to avoid asking for a new one each time.
        mInflater = LayoutInflater.from(context);
        this._activity=context;
        this.screenWidth = screenWidth;

        months = new ArrayList<String>();
        months.add("No Item Selected");
        months.add("None");
        months.add("Entertainment");
        months.add("Games");
        months.add("News/Books");
        months.add("Social Networking");
        months.add("Utilities");
        months.add("Texting");
        months.add("Web Browsers");


        // Creating adapter for spinner
        dataAdapter = new ArrayAdapter<String>(_activity,
                android.R.layout.simple_spinner_item, months);

        // Drop down layout style - list view with radio button
        dataAdapter.setDropDownViewResource(android.R.layout.select_dialog_singlechoice);


    }

    public int getCount() {

        return mApps.size();
    }

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

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

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

        final AppViewHolder holder;

        viewposition=position;
        if(convertView == null) {
            convertView = mInflater.inflate(R.layout.row, null);
            // creates a ViewHolder and stores a reference to the children view we want to bind data to
            holder = new AppViewHolder();

            holder.spiner=(Spinner)convertView.findViewById(R.id.spinner);
            holder.offtext=(TextView)convertView.findViewById(R.id.off_txt);


            holder.offTxt = (TextView) convertView.findViewById(R.id.off_txt);
            holder.apptitleTxt = (TextView) convertView.findViewById(R.id.apptitle_txt);
            Typeface typeface = Typeface.createFromAsset(_activity.getAssets(),"CHICM___.TTF");
            holder.apptitleTxt.setTypeface(typeface);
            holder.offTxt.setTypeface(typeface);

            if(screenWidth>480){
                holder.offTxt.setTextSize(30);
                holder.apptitleTxt.setTextSize(30);
            }
            convertView.setTag(holder);
        } else { 
            holder = (AppViewHolder) convertView.getTag();
        }

        holder.setTitle(mApps.get(position).getTitle(),mApps.get(position).getVersionName());

        notifyDataSetChanged();

        holder.offTxt.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                holder.spiner.performClick();

            }
        });

        holder.spiner.setAdapter(dataAdapter);
        holder.spiner.setOnItemSelectedListener(new OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
                spinerposition=arg2;
                switch (spinerposition)
                {
                case 1:

                    holder.offtext.setText("None");
                    break;
                case 2:

                    holder.offtext.setText("Entertainment");
                    break;
                case 3:

                    holder.offtext.setText("Games");
                    break;
                case 4:

                    holder.offtext.setText("News/Books");
                    break;
                case 5:

                    holder.offtext.setText("Social Networking");
                    break;
                case 6:

                    holder.offtext.setText("Utilities");
                    break;
                case 7:

                    holder.offtext.setText("Texting");
                    break;
                case 8:

                    holder.offtext.setText("Web Browsers");
                    break;
                }
            }
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });
        return convertView; 
    }



    /**
     * Sets the list of apps to be displayed.
     * 
     * @param list the list of apps to be displayed
     */
    public void setListItems(List<App> list) { 
        mApps = list; 
    }

    /**
     * A view holder which is used to re/use views inside a list.
     */
    public class AppViewHolder {

        private TextView mTitle = null;
        private TextView apptitleTxt = null;
        private TextView offTxt = null;
        private Spinner spiner=null;
        public TextView offtext;
        /**
         * Sets the text to be shown as the app's title
         * 
         * @param title the text to be shown inside the list row
         */
        public void setTitle(String title,String category) {
            apptitleTxt.setText(title);
//          offtext.setText(category);
        }
    }

}
Selfexecuting answered 17/6, 2013 at 7:11 Comment(2)
Is the title for holder.offtext not getting set correctly? If so i dont see you title everytime you get in getView method. You do it only in your OnItemSelectedListener. Because of which it would show stale data at some time.Glissando
have a look at my view #6470589Amaya
S
0

I got the solution for the issue. I have introduced a dialogList() in which I am working with a ArrayList. Below I have mentioned the code of my Adapter class.

public class AppListAdapter extends BaseAdapter {

    private LayoutInflater mInflater;
    private List<App> mApps = Constants.list;
    private Context _activity;
    ArrayList<String> months=null;
    ArrayAdapter<String> dataAdapter =null;
    int spinerposition;
    Context contextfordatabase=null;

    int temp=0;
    private int screenWidth;


    /**
     * Constructor.
     * 
     * @param context the application context which is needed for the layout inflater
     * @param screenWidth 
     */
    public AppListAdapter(Context context, int screenWidth) {
        contextfordatabase=context;
        // Cache the LayoutInflate to avoid asking for a new one each time.
        mInflater = LayoutInflater.from(context);
        this._activity=context;
        this.screenWidth = screenWidth;

        months = new ArrayList<String>();
        months.add("No Item Selected");
        months.add("None");
        months.add("Entertainment");
        months.add("Games");
        months.add("News/Books");
        months.add("Social Networking");
        months.add("Utilities");
        months.add("Texting");
        months.add("Web Browsers");
    }

    public int getCount() {

        return mApps.size();
    }

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

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

    public class AppViewHolder {

        private TextView mTitle = null;
        private TextView apptitleTxt = null;
        private TextView offTxt = null;
        private Spinner spiner=null;
        public TextView offtext;
    }

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

        final AppViewHolder holder;
        if(convertView == null) {
            convertView = mInflater.inflate(R.layout.row, null);
            // creates a ViewHolder and stores a reference to the children view we want to bind data to
            holder = new AppViewHolder();

            holder.spiner=(Spinner)convertView.findViewById(R.id.spinner);
            holder.offtext=(TextView)convertView.findViewById(R.id.off_txt);

            holder.apptitleTxt = (TextView) convertView.findViewById(R.id.apptitle_txt);
            Typeface typeface = Typeface.createFromAsset(_activity.getAssets(),"CHICM___.TTF");
            holder.apptitleTxt.setTypeface(typeface);
            holder.offtext.setTypeface(typeface);

            if(screenWidth>480){
                holder.offtext.setTextSize(30);
                holder.apptitleTxt.setTextSize(30);
            }
            convertView.setTag(holder);
        } else { 
            holder = (AppViewHolder) convertView.getTag();
        }

        holder.offtext.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                dialogList(holder.offtext, position);
            }
        });

        holder.apptitleTxt.setText(mApps.get(position).getTitle());
        holder.offtext.setText(mApps.get(position).getVersionName());

        return convertView; 
    }

    /**
     * Sets the list of apps to be displayed.
     * 
     * @param list the list of apps to be displayed
     */
    public void setListItems(List<App> list) { 
        mApps = list; 
    }

    public void dialogList(final TextView textView, final int clickedPosition){
        Builder builder = new AlertDialog.Builder(_activity);
        builder.setTitle("Select Category");
        builder.setItems(R.array.category_list, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) 
            {
                textView.setText(months.get(which+1));
                App app = new App();
                app.setTitle(mApps.get(clickedPosition).getTitle());
                app.setPackageName(mApps.get(clickedPosition).getPackageName());
                app.setVersionName(months.get(which+1));
                app.setVersionCode(mApps.get(clickedPosition).getVersionCode());
                mApps.set(clickedPosition, app);
                System.out.println(clickedPosition+" : "+months.get(which+1));


                update_database(mApps.get(clickedPosition).getPackageName(),months.get(which+1));


                AppListAdapter.this.notifyDataSetChanged();
            }

        });
        builder.create();
        builder.show();
    }

    public void update_database(String packageName, String string) {
        CallBackDatabase callback = new CallBackDatabase(contextfordatabase);
        callback.open();
        Cursor cursor =callback.getAll(packageName);
        int y=cursor.getCount();
        int j=0;
        if(y!=0)
        {
            callback.UpdateCategory(packageName, string);
        }
        else
        {
            callback.InsertAppInfo(null, packageName, "0", "0", "0", "null", string);
        }
        cursor.deactivate();
        cursor.close();
        callback.close();
    }

}
Selfexecuting answered 18/6, 2013 at 7:16 Comment(1)
Thanks Sam , I was also facing the issue.It helped me to get rid of that problem.Priestly
O
2

This is because ListView is reusing all previous Views, which are scrolled (not visible).

Please check out this topic.

Olvera answered 17/6, 2013 at 7:23 Comment(1)
Yeah... I am done with this issue.. got huge knowledge about list view properties. thanks by the way.Selfexecuting
R
1

Change

   if(convertView == null) {
            convertView = mInflater.inflate(R.layout.row, null);
            // creates a ViewHolder and stores a reference to the children view we want to bind data to
            holder = new AppViewHolder();

            holder.spiner=(Spinner)convertView.findViewById(R.id.spinner);
            holder.offtext=(TextView)convertView.findViewById(R.id.off_txt);


            holder.offTxt = (TextView) convertView.findViewById(R.id.off_txt);
            holder.apptitleTxt = (TextView) convertView.findViewById(R.id.apptitle_txt);
            Typeface typeface = Typeface.createFromAsset(_activity.getAssets(),"CHICM___.TTF");
            holder.apptitleTxt.setTypeface(typeface);
            holder.offTxt.setTypeface(typeface);

            if(screenWidth>480){
                holder.offTxt.setTextSize(30);
                holder.apptitleTxt.setTextSize(30);
            }
            convertView.setTag(holder);
        } else { 
            holder = (AppViewHolder) convertView.getTag();
        }

TO

convertView = mInflater.inflate(R.layout.row, null);
    // creates a ViewHolder and stores a reference to the children view we want to bind data to
    holder = new AppViewHolder();

    holder.spiner=(Spinner)convertView.findViewById(R.id.spinner);
    holder.offtext=(TextView)convertView.findViewById(R.id.off_txt);


    holder.offTxt = (TextView) convertView.findViewById(R.id.off_txt);
    holder.apptitleTxt = (TextView) convertView.findViewById(R.id.apptitle_txt);
    Typeface typeface = Typeface.createFromAsset(_activity.getAssets(),"CHICM___.TTF");
    holder.apptitleTxt.setTypeface(typeface);
    holder.offTxt.setTypeface(typeface);

    if(screenWidth>480){
        holder.offTxt.setTextSize(30);
        holder.apptitleTxt.setTextSize(30);
    }
    convertView.setTag(holder);

Now you can see that every thing will work properly. This is not the best way to fix the problem!, to need to manage the state of you items when using convert view for view recycling.

EDIT

public class AppListAdapter extends BaseAdapter {

    private LayoutInflater mInflater;
    private List<App> mApps = Constants.list;
    private Context _activity;
    ArrayList<String> months=null;
    ArrayAdapter<String> dataAdapter =null;
    int spinerposition;
    int viewposition;

    int temp=0;
    private int screenWidth;


     ArrayList<String> vals=null;


    /**
     * Constructor.
     * 
     * @param context the application context which is needed for the layout inflater
     * @param screenWidth 
     */
    public AppListAdapter(Context context, int screenWidth) {
        // Cache the LayoutInflate to avoid asking for a new one each time.
        mInflater = LayoutInflater.from(context);
        this._activity=context;
        this.screenWidth = screenWidth;

        months = new ArrayList<String>();
        months.add("No Item Selected");
        months.add("None");
        months.add("Entertainment");
        months.add("Games");
        months.add("News/Books");
        months.add("Social Networking");
        months.add("Utilities");
        months.add("Texting");
        months.add("Web Browsers");

        vals = new ArrayList<String>();


        // Creating adapter for spinner
        dataAdapter = new ArrayAdapter<String>(_activity,
                android.R.layout.simple_spinner_item, months);

        // Drop down layout style - list view with radio button
        dataAdapter.setDropDownViewResource(android.R.layout.select_dialog_singlechoice);


    }

    public int getCount() {

        return mApps.size();
    }

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

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

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

        final AppViewHolder holder;

        viewposition=position;

            convertView = mInflater.inflate(R.layout.row, null);
            // creates a ViewHolder and stores a reference to the children view we want to bind data to
            holder = new AppViewHolder();

            holder.spiner=(Spinner)convertView.findViewById(R.id.spinner);
            holder.offtext=(TextView)convertView.findViewById(R.id.off_txt);


            holder.offTxt = (TextView) convertView.findViewById(R.id.off_txt);
            holder.apptitleTxt = (TextView) convertView.findViewById(R.id.apptitle_txt);
            Typeface typeface = Typeface.createFromAsset(_activity.getAssets(),"CHICM___.TTF");
            holder.apptitleTxt.setTypeface(typeface);
            holder.offTxt.setTypeface(typeface);

            if(screenWidth>480){
                holder.offTxt.setTextSize(30);
                holder.apptitleTxt.setTextSize(30);
            }
            convertView.setTag(holder);


if(vals.get(position)!=null)
{
 holder.offtext.setText(vals.get(position));
}


        holder.setTitle(mApps.get(position).getTitle(),mApps.get(position).getVersionName());

        notifyDataSetChanged();

        holder.offTxt.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                holder.spiner.performClick();

            }
        });

        holder.spiner.setAdapter(dataAdapter);
        holder.spiner.setOnItemSelectedListener(new OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
                spinerposition=arg2;
                switch (spinerposition)
                {
                case 1:

                    holder.offtext.setText("None");
                    break;
                case 2:

                    holder.offtext.setText("Entertainment");
                    break;
                case 3:

                    holder.offtext.setText("Games");
                    break;
                case 4:

                    holder.offtext.setText("News/Books");
                    break;
                case 5:

                    holder.offtext.setText("Social Networking");
                    break;
                case 6:

                    holder.offtext.setText("Utilities");
                    break;
                case 7:

                    holder.offtext.setText("Texting");
                    break;
                case 8:

                    holder.offtext.setText("Web Browsers");
                    break;
                }
         vals.add(arg2,holder.offtext.getText());
            }
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });
        return convertView; 
    }



    /**
     * Sets the list of apps to be displayed.
     * 
     * @param list the list of apps to be displayed
     */
    public void setListItems(List<App> list) { 
        mApps = list; 
    }

    /**
     * A view holder which is used to re/use views inside a list.
     */
    public class AppViewHolder {

        private TextView mTitle = null;
        private TextView apptitleTxt = null;
        private TextView offTxt = null;
        private Spinner spiner=null;
        public TextView offtext;
        /**
         * Sets the text to be shown as the app's title
         * 
         * @param title the text to be shown inside the list row
         */
        public void setTitle(String title,String category) {
            apptitleTxt.setText(title);
//          offtext.setText(category);
        }
    }

}
Railing answered 17/6, 2013 at 7:24 Comment(3)
I have done the change, but whenever I scroll down and back to up the value re-initialized to None.Selfexecuting
You need to save you values into an array list or some where else and then restore it getView() to the offTxt Textview.Railing
Its still not working... 1stly I was getting crash in the Arraylist, after handling the crash, the problem remains the same.Selfexecuting
S
0

I got the solution for the issue. I have introduced a dialogList() in which I am working with a ArrayList. Below I have mentioned the code of my Adapter class.

public class AppListAdapter extends BaseAdapter {

    private LayoutInflater mInflater;
    private List<App> mApps = Constants.list;
    private Context _activity;
    ArrayList<String> months=null;
    ArrayAdapter<String> dataAdapter =null;
    int spinerposition;
    Context contextfordatabase=null;

    int temp=0;
    private int screenWidth;


    /**
     * Constructor.
     * 
     * @param context the application context which is needed for the layout inflater
     * @param screenWidth 
     */
    public AppListAdapter(Context context, int screenWidth) {
        contextfordatabase=context;
        // Cache the LayoutInflate to avoid asking for a new one each time.
        mInflater = LayoutInflater.from(context);
        this._activity=context;
        this.screenWidth = screenWidth;

        months = new ArrayList<String>();
        months.add("No Item Selected");
        months.add("None");
        months.add("Entertainment");
        months.add("Games");
        months.add("News/Books");
        months.add("Social Networking");
        months.add("Utilities");
        months.add("Texting");
        months.add("Web Browsers");
    }

    public int getCount() {

        return mApps.size();
    }

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

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

    public class AppViewHolder {

        private TextView mTitle = null;
        private TextView apptitleTxt = null;
        private TextView offTxt = null;
        private Spinner spiner=null;
        public TextView offtext;
    }

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

        final AppViewHolder holder;
        if(convertView == null) {
            convertView = mInflater.inflate(R.layout.row, null);
            // creates a ViewHolder and stores a reference to the children view we want to bind data to
            holder = new AppViewHolder();

            holder.spiner=(Spinner)convertView.findViewById(R.id.spinner);
            holder.offtext=(TextView)convertView.findViewById(R.id.off_txt);

            holder.apptitleTxt = (TextView) convertView.findViewById(R.id.apptitle_txt);
            Typeface typeface = Typeface.createFromAsset(_activity.getAssets(),"CHICM___.TTF");
            holder.apptitleTxt.setTypeface(typeface);
            holder.offtext.setTypeface(typeface);

            if(screenWidth>480){
                holder.offtext.setTextSize(30);
                holder.apptitleTxt.setTextSize(30);
            }
            convertView.setTag(holder);
        } else { 
            holder = (AppViewHolder) convertView.getTag();
        }

        holder.offtext.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                dialogList(holder.offtext, position);
            }
        });

        holder.apptitleTxt.setText(mApps.get(position).getTitle());
        holder.offtext.setText(mApps.get(position).getVersionName());

        return convertView; 
    }

    /**
     * Sets the list of apps to be displayed.
     * 
     * @param list the list of apps to be displayed
     */
    public void setListItems(List<App> list) { 
        mApps = list; 
    }

    public void dialogList(final TextView textView, final int clickedPosition){
        Builder builder = new AlertDialog.Builder(_activity);
        builder.setTitle("Select Category");
        builder.setItems(R.array.category_list, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) 
            {
                textView.setText(months.get(which+1));
                App app = new App();
                app.setTitle(mApps.get(clickedPosition).getTitle());
                app.setPackageName(mApps.get(clickedPosition).getPackageName());
                app.setVersionName(months.get(which+1));
                app.setVersionCode(mApps.get(clickedPosition).getVersionCode());
                mApps.set(clickedPosition, app);
                System.out.println(clickedPosition+" : "+months.get(which+1));


                update_database(mApps.get(clickedPosition).getPackageName(),months.get(which+1));


                AppListAdapter.this.notifyDataSetChanged();
            }

        });
        builder.create();
        builder.show();
    }

    public void update_database(String packageName, String string) {
        CallBackDatabase callback = new CallBackDatabase(contextfordatabase);
        callback.open();
        Cursor cursor =callback.getAll(packageName);
        int y=cursor.getCount();
        int j=0;
        if(y!=0)
        {
            callback.UpdateCategory(packageName, string);
        }
        else
        {
            callback.InsertAppInfo(null, packageName, "0", "0", "0", "null", string);
        }
        cursor.deactivate();
        cursor.close();
        callback.close();
    }

}
Selfexecuting answered 18/6, 2013 at 7:16 Comment(1)
Thanks Sam , I was also facing the issue.It helped me to get rid of that problem.Priestly

© 2022 - 2024 — McMap. All rights reserved.