When I try extending the View class to a subclass that will also
underline portions of text, the code compiles okay but results in a
runtime exception apparently due to an improper class cast.  Does
anyone see what I've done wrong or have suggestions about getting
access to the Canvas of ListView items so portions of text can be
underlined?

Here is the code, which is the Efficient Adapter View/List example
from ApiDemos with an added UnderlinedView class.

- - - -

package com.example.android.apis.view;

import android.app.ListActivity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Demonstrates how to write an efficient list adapter. The adapter
used in this example binds
 * to an ImageView and to a TextView for each row in the list.
 *
 * To work efficiently the adapter implemented here uses two
techniques:
 * - It reuses the convertView passed to getView() to avoid inflating
View when it is not necessary
 * - It uses the ViewHolder pattern to avoid calling findViewById()
when it is not necessary
 *
 * The ViewHolder pattern consists in storing a data structure in the
tag of the view returned by
 * getView(). This data structures contains references to the views we
want to bind data to, thus
 * avoiding calls to findViewById() every time getView() is invoked.
 */
public class List14 extends ListActivity {

        private static class UnderlinedView extends View {
                public UnderlinedView(Context context) {
                        super(context);
                }
                public UnderlinedView(Context context, AttributeSet as) {
                        super(context, as);
                }
                public UnderlinedView(Context context, AttributeSet as, int i) {
                        super(context, as, i);
                }
            @Override
            protected void onDraw(Canvas canvas){
                super.onDraw(canvas);

                // Would like to do some line drawing here (e.g., underlining
portions of text)
            }
        }

    private static class EfficientAdapter extends BaseAdapter {
        private LayoutInflater mInflater;
        private Bitmap mIcon1;
        private Bitmap mIcon2;

        public EfficientAdapter(Context context) {
            // Cache the LayoutInflate to avoid asking for a new one
each time.
            mInflater = LayoutInflater.from(context);

            // Icons bound to the rows.
            mIcon1 = BitmapFactory.decodeResource(context.getResources
(), R.drawable.icon48x48_1);
            mIcon2 = BitmapFactory.decodeResource(context.getResources
(), R.drawable.icon48x48_2);
        }

        /**
         * The number of items in the list is determined by the number
of speeches
         * in our array.
         *
         * @see android.widget.ListAdapter#getCount()
         */
        public int getCount() {
            return DATA.length;
        }

        /**
         * Since the data comes from an array, just returning the
index is
         * sufficent to get at the data. If we were using a more
complex data
         * structure, we would return whatever object represents one
row in the
         * list.
         *
         * @see android.widget.ListAdapter#getItem(int)
         */
        public Object getItem(int position) {
            return position;
        }

        /**
         * Use the array index as a unique id.
         *
         * @see android.widget.ListAdapter#getItemId(int)
         */
        public long getItemId(int position) {
            return position;
        }

        /**
         * Make a view to hold each row.
         *
         * @see android.widget.ListAdapter#getView(int,
android.view.View,
         *      android.view.ViewGroup)
         */
        public View getView(int position, View convertView, ViewGroup
parent) {
            // A ViewHolder keeps references to children views to
avoid unneccessary calls
            // to findViewById() on each row.
            ViewHolder holder;
            UnderlinedView underlinedView = (UnderlinedView)
convertView;

            // When convertView is not null, we can reuse it directly,
there is no need
            // to reinflate it. We only inflate a new View when the
convertView supplied
            // by ListView is null.
            if (convertView == null) {
                convertView = mInflater.inflate
(R.layout.list_item_icon_text, null);
                underlinedView = (UnderlinedView)convertView;

                // Creates a ViewHolder and store references to the
two children views
                // we want to bind data to.
                holder = new ViewHolder();
                holder.text = (TextView) underlinedView.findViewById
(R.id.text);
                holder.icon = (ImageView) underlinedView.findViewById
(R.id.icon);

                underlinedView.setTag(holder);
            } else {
                // Get the ViewHolder back to get fast access to the
TextView
                // and the ImageView.
                holder = (ViewHolder) underlinedView.getTag();
            }

            // Bind the data efficiently with the holder.
            holder.text.setText(DATA[position]);
            holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 :
mIcon2);

            return underlinedView;
        }

        static class ViewHolder {
            TextView text;
            ImageView icon;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setListAdapter(new EfficientAdapter(this));
    }

    private static final String[] DATA = {
            "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam",
            "Abondance", "Ackawi", "Acorn", "Adelost", "Affidelice au
Chablis",
            "... a lot more strings in ApiDemos sample ...",
            "Zanetti Grana Padano", "Zanetti Parmigiano Reggiano"};
}

- - - -

The stack trace from logcat is

D/AndroidRuntime(  753): Shutting down VM
W/dalvikvm(  753): threadid=3: thread exiting with uncaught exception
(group=0x4000fe70)
E/AndroidRuntime(  753): Uncaught handler: thread main exiting due to
uncaught exception
E/AndroidRuntime(  753): java.lang.ClassCastException:
android.widget.LinearLayout
E/AndroidRuntime(  753):        at
com.example.android.apis.view.List14$EfficientAdapter.getView
(List14.java:127)
E/AndroidRuntime(  753):        at android.widget.AbsListView.obtainView
(AbsListView.java:1269)
E/AndroidRuntime(  753):        at android.widget.ListView.makeAndAddView
(ListView.java:1623)
E/AndroidRuntime(  753):        at android.widget.ListView.fillDown
(ListView.java:607)
E/AndroidRuntime(  753):        at android.widget.ListView.fillFromTop
(ListView.java:664)
E/AndroidRuntime(  753):        at android.widget.ListView.layoutChildren
(ListView.java:1481)
E/AndroidRuntime(  753):        at android.widget.AbsListView.onLayout
(AbsListView.java:1113)
E/AndroidRuntime(  753):        at android.view.View.layout(View.java:6133)
E/AndroidRuntime(  753):        at android.widget.FrameLayout.onLayout
(FrameLayout.java:333)
E/AndroidRuntime(  753):        at android.view.View.layout(View.java:6133)
E/AndroidRuntime(  753):        at android.widget.LinearLayout.setChildFrame
(LinearLayout.java:1119)
E/AndroidRuntime(  753):        at android.widget.LinearLayout.layoutVertical
(LinearLayout.java:998)
E/AndroidRuntime(  753):        at android.widget.LinearLayout.onLayout
(LinearLayout.java:918)
E/AndroidRuntime(  753):        at android.view.View.layout(View.java:6133)
E/AndroidRuntime(  753):        at android.widget.FrameLayout.onLayout
(FrameLayout.java:333)
E/AndroidRuntime(  753):        at android.view.View.layout(View.java:6133)
E/AndroidRuntime(  753):        at android.view.ViewRoot.performTraversals
(ViewRoot.java:929)
E/AndroidRuntime(  753):        at android.view.ViewRoot.handleMessage
(ViewRoot.java:1482)
E/AndroidRuntime(  753):        at android.os.Handler.dispatchMessage
(Handler.java:99)
E/AndroidRuntime(  753):        at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(  753):        at android.app.ActivityThread.main
(ActivityThread.java:3948)
E/AndroidRuntime(  753):        at java.lang.reflect.Method.invokeNative
(Native Method)
E/AndroidRuntime(  753):        at java.lang.reflect.Method.invoke
(Method.java:521)
E/AndroidRuntime(  753):        at com.android.internal.os.ZygoteInit
$MethodAndArgsCaller.run(ZygoteInit.java:782)
E/AndroidRuntime(  753):        at com.android.internal.os.ZygoteInit.main
(ZygoteInit.java:540)
E/AndroidRuntime(  753):        at dalvik.system.NativeStart.main(Native
Method)

where line 127 is the class cast at

                convertView = mInflater.inflate
(R.layout.list_item_icon_text, null);
                underlinedView = (UnderlinedView)convertView;


Best regards,
Greg



On Jul 26, 1:46 pm, greg <[email protected]> wrote:
> After reading the enlightening excerpt from Mark Murphy's _The Busy
> Coder's Guide to Android Development_ at
>
>    http://commonsware.com/Android/excerpt.pdf,
>
> I believe that the Efficient Adapter's getView is the access point I
> was looking for.
>
> I'll post the code if I get it working.
>
> - Greg
>
> On Jul 25, 11:34 pm, greg <[email protected]> wrote:
>
> > Although I'm not yet quite fully comfortable with Java or Eclipse, I
> > thought by using the SDK ApiDemos Views/Lists/14. Efficient Adapter
> > sample code as a starting point and the 'Modifying an Existing View
> > Type' instructions at <SDK>/docs/guide/topics/ui/custom-
> > components.html, I might be able to make an extendedListViewsearch
> > for, scroll to, and underline user entered text.
>
> > The problem is, I don't see an onDraw() method to override in the
> >ListViewor BaseAdapter classes.  How should I get access to the
> >Canvasof theListViewitems?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Beginners" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-beginners?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to