awaelchli
awaelchli

Reputation: 886

Why is ListView not scrolling consistently?

I am currently working on a ListView that contains around 80 to 100 items (TextViews). I don't think it is too much content, but when i scroll (with fingers) the ListView is bobbing or laging. However, when I use the "fast-scroll-button" - that thing on the right of the ListView - the scrolling appears very consistent and smooth.

Did anyone have the same problem? I tested the ListView on my HTC Sensation.

Here is my ListView code:

<ListView
     android:id="@+id/list_view"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     android:scrollingCache="true">

</ListView>

And the Java code:

adptr = new ArrayAdapter<String>(iF, R.layout.list_item, showing) {

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

            LinearLayout lin = new LinearLayout(this.getContext());
            lin.setOrientation(LinearLayout.HORIZONTAL);

            // Icon
            ImageView v = new ImageView(this.getContext());
            // v.setBackgroundDrawable(iF.getResources().getDrawable(R.drawable.cube_icon));

            // Text
            TextView txt = new TextView(this.getContext());
            txt.setTextSize(Float.valueOf(prefs.getString("pref_txtSize", "12")));
            txt.setPadding(10, 10, 10, 10);
            txt.setText(this.getItem(position));
            txt.setTextColor(getLineColor(position));

            // Shortcut
            LinearLayout shortLin = new LinearLayout(this.getContext());
            shortLin.setGravity(Gravity.RIGHT);

            LayoutParams par = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
            shortLin.setLayoutParams(par);

            TextView s = new TextView(this.getContext());
            s.setTextSize(Float.valueOf(prefs.getString("pref_txtSize", "12")));
            s.setWidth(iF.getResources().getDimensionPixelSize(R.dimen.shortcutWidth));
            s.setPadding(10, 10, 10, 10);

            s.setText(getShortcut(position));

            shortLin.addView(s);

            // Return
            txt.invalidate();
            v.invalidate();
            s.invalidate();

            lin.addView(v);
            lin.addView(txt);
            lin.addView(shortLin);

            return lin;
        }
    };

As you can see, I made a customized ListView. The ArrayAdapter will be added in a different method (not shown here).

Thanks in advance

Adrian

Upvotes: 0

Views: 2184

Answers (3)

awaelchli
awaelchli

Reputation: 886

Finally, I came up with this solution:

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

            View view = convertView;
            ViewHolder holder;

            if (view == null) {

                LayoutInflater inflater = (LayoutInflater) iF.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.list_item, parent, false);

                holder = new ViewHolder();
                holder.title = (TextView) view.findViewById(R.id.item_text);
                holder.shortcut = (TextView) view.findViewById(R.id.item_short);

                holder.title.setId(1);
                holder.shortcut.setId(2);

                holder.title.setText(getItem((position)));
                holder.shortcut.setText(getShortcut(position));

                holder.title.setTextSize(Float.valueOf(prefs.getString("pref_txtSize", "12")));
                holder.shortcut.setTextSize(Float.valueOf(prefs.getString("prefs_txtSize", "12")));

                view.setTag(holder);
            } else {
                holder = (ViewHolder) view.getTag();

                TextView title = (TextView) convertView.findViewById(1);
                title.setText(getItem(position));

                TextView shortcut = (TextView) convertView.findViewById(2);
                shortcut.setText(getShortcut(position));
            }

            return view;
        }

I am really happy right now that it worked. It is 00:33, so I think I go to bed now. Enough work for today (yesterday :)

Thanks for all the support

Upvotes: 0

Brian Dupuis
Brian Dupuis

Reputation: 8176

You're creating every View element for your list dynamically every time you pull a view. That's possibly the most inefficient mechanism ever :).

As a first step, see if you can layout your view in XML. Makes things easier to manage.

Even if you don't do that, use the convertView parameter. Its sole reason for existence is to keep you from having to reallocate views if possible. If convertView is non-null, it has all the views you created in a previous invocation of getView(). All you have to do is fill in the appropriate information in each view (essentially, in your case, the setText() calls). If convertView is null, create your views.

Also, don't invalidate(). At a minimum, without the XML layout, here's a rewritten version that should be a bit faster.

@Override
public View getView(int position, View convertView, ViewGroup grp) {
    if(convertView == null) {
        LinearLayout lin = new LinearLayout(this.getContext());
        lin.setOrientation(LinearLayout.HORIZONTAL);

        // Icon
        ImageView v = new ImageView(this.getContext());
        // v.setBackgroundDrawable(iF.getResources().getDrawable(R.drawable.cube_icon));

        // Text
        TextView txt = new TextView(this.getContext());
        txt.setId(1);
        txt.setTextSize(Float.valueOf(prefs.getString("pref_txtSize", "12")));
        txt.setPadding(10, 10, 10, 10);
        txt.setTextColor(getLineColor(position));

        // Shortcut
        LinearLayout shortLin = new LinearLayout(this.getContext());
        shortLin.setGravity(Gravity.RIGHT);

        LayoutParams par = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        shortLin.setLayoutParams(par);

        TextView s = new TextView(this.getContext());
        s.setId(2);
        s.setTextSize(Float.valueOf(prefs.getString("pref_txtSize", "12")));
        s.setWidth(iF.getResources().getDimensionPixelSize(R.dimen.shortcutWidth));
        s.setPadding(10, 10, 10, 10);

        shortLin.addView(s);
        lin.addView(v);
        lin.addView(txt);
        lin.addView(shortLin);
    }

    TextView txt = (TextView)convertView.findViewById(1);
    txt.setText(this.getItem(position));
    TextView txt = (TextView)convertView.findViewById(2);
    txt.setText(getShortcut(position));


    return lin;
}

Again, not the best way or a best practice, but this should work.

Upvotes: 2

Damian Piwowarski
Damian Piwowarski

Reputation: 814

Do you remember about cache?

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

    View view = convertView;
    ViewHolder holder;

    if (view == null) {

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater
                .inflate(R.layout.list_view_home_item, parent, false);

        holder = new ViewHolder();
        holder.title = (TextView) view
                .findViewById(R.id.textView);

        holder.title.setText("blah");
        view.setTag(holder);            
    } else {        
        holder = (ViewHolder) view.getTag();
    }

    return view;

and

    static class ViewHolder {
    TextView title;
}

?

Upvotes: 4

Related Questions