1

Currently I am using code to give text suggestion. I would like to add another text and image. How do I do that? Currently, I am using the code below.I shows text but image is not displayed .How do I set the image ?

public class AutoCompleteTextViewActivity extends Activity{

ImageLoader imageLoader;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
        .cacheInMemory(true)
        .cacheOnDisc(true)
        .build();

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
        .defaultDisplayImageOptions(defaultOptions)
        .build();
ImageLoader.getInstance().init(config);


        AutoCompleteTextView actv = new AutoCompleteTextView(this);
        actv.setThreshold(1);
        final String[] from = {BaseColumns._ID, "name", "artist", "title"};
        int[] to = {R.id.list_image, R.id.textView1, R.id.textView2, R.id.textView3};
        final SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.list_row, null, from, to);
        adapter.setStringConversionColumn(1);
        ViewBinder viewBinder = new ViewBinder() {
             public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
                 if (columnIndex == 0) {
                     ImageView iv = (ImageView) view;
                     Bitmap bitmap = cursor.getExtras().getParcelable("image");
                     if (bitmap != null) {
                         iv.setImageBitmap(bitmap);
                     }
                     return true;
                 }
                 return false;
             }
        };
        adapter.setViewBinder(viewBinder);
        FilterQueryProvider provider = new FilterQueryProvider() {
            ExecutorService mPool = Executors.newCachedThreadPool();
            Uri URI = Uri.parse("adapter://autocomplete");

            public Cursor runQuery(CharSequence constraint) {
                if (constraint == null) {
                    return null;
                }
                try {
                    return callWebService(constraint, from);
                } catch (JSONException e) {
                    e.printStackTrace();
                    return null;
                }
            }

            // here you make the web request
            private Cursor callWebService(CharSequence constraint, String[] columnNames) throws JSONException {
                Log.d("TAG", "callWebService for: " + constraint);
                MatrixCursor cursor = new MyMatrixCursor(columnNames);

                // TODO do real network request
                // call web service here and keep the result in "jsonStr" 

            //  String a=constraint;
                JSONObject json=JSONfunctions.getJSONfromURL("http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist="+ constraint +"&api_key=63692beaaf8ba794a541bca291234cd3&format=json");



                JSONObject js1=json.getJSONObject("artist");
                JSONObject js=js1.getJSONObject("similar");
                JSONArray resultArray = js.getJSONArray("artist");


                int length = resultArray.length();
                for (int i = 0; i < length; i++) {
                    String data = resultArray.getJSONObject(i).getString("name");

                    String dataimage = resultArray.getJSONObject(i).getJSONArray("image").getJSONObject(i).getString("#text");

                    cursor.newRow().add(i)
                        .add(data)
                        .add(data)
                        .add(data);

                    String link = dataimage;
                    // get cached Bundle based on "link" (use HashMap<String, Bundle>)
                    // or if new link initiate async request for getting the bitmap

                    // TODO implement HashMap caching

                    // new async request
                    Bundle extras = new Bundle();
                    try {
                        mPool.submit(new ImageRequest(link, extras));
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
                    cursor.respond(extras);
                }
                cursor.setNotificationUri(getContentResolver(), URI);
                return cursor;
            }

            class ImageRequest implements Runnable {
                private URL mUrl;
                private Bundle mExtra;

                public ImageRequest(String link, Bundle extra) throws MalformedURLException {
                    mUrl = new URL(link);
                    mExtra = extra;
                }

                public void run() {
                            String TAG="log";
                            // TODO do real network request
                            // simulate network delay
//                          Log.d(TAG, "getting " + mUrl);
//                          try {
//                              Thread.sleep(2000 + (long) (4000 * Math.random()));
//                          } catch (InterruptedException e) {
//                              e.printStackTrace();
//                          }

                            Bitmap b = imageLoader.loadImageSync(mUrl.toString());
                         //   Bitmap b = BitmapFactory.decodeResource(getResources(), mUrl.toString());
                            mExtra.putParcelable("image", b);
                            getContentResolver().notifyChange(URI, null);
                            Log.d(TAG, "run got a bitmap " + b.getWidth() + "x" + b.getHeight());

                }


            }
        };
        adapter.setFilterQueryProvider(provider);
        actv.setAdapter(adapter);



        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        setContentView(actv, params);
    }

}

///////////////

MyMatrixCursor //////////

public class MyMatrixCursor extends MatrixCursor {
    List<Bundle> mBundles = new ArrayList<Bundle>();

    public MyMatrixCursor(String[] columnNames) {
        super(columnNames);
    }

    @Override
    public Bundle respond(Bundle extras) {
        mBundles.add(extras);
        return extras;
    }

    @Override
    public Bundle getExtras() {
        return mBundles.get(mPos);
    }
}

////////

JSONfunctions ///////

public class JSONfunctions {

    public static JSONObject getJSONfromURL(String url){
        InputStream is = null;
        String result = "";
        JSONObject jArray = null;

        //http post
        try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost(url);
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();

        }catch(Exception e){
                Log.e("log_tag", "Error in http connection "+e.toString());
        }

      //convert response to string
        try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                }
                is.close();
                result=sb.toString();
        }catch(Exception e){
                Log.w("log_tag", "Error converting result "+e.toString());
        }

        try{

            jArray = new JSONObject(result);            
        }catch(JSONException e){
                Log.w("log_tag", "Error parsing data "+e.toString());
        }

        return jArray;
    }
}

////////

main.xml ///

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Pick Artist"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <AutoCompleteTextView
        android:id="@+id/actv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:completionThreshold="1"> <requestFocus />
    </AutoCompleteTextView>
    <TextView
        android:id="@+id/selection"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

/////

list_row.xml ///

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:orientation="horizontal"
    android:padding="5dip" >

    <!--  ListRow Left sied Thumbnail image -->
    <LinearLayout android:id="@+id/thumbnail" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="3dip"      
        android:layout_alignParentLeft="true"
        android:layout_marginRight="5dip">

        <ImageView     
            android:id="@+id/list_image"   
        android:layout_width="wrap_content"  
  android:layout_height="wrap_content"  
  android:adjustViewBounds="true"  
  android:maxWidth="42dp"  
  android:maxHeight="42dp"  
  android:src="@drawable/ic_launcher"
  android:scaleType="fitCenter"  
  android:layout_marginLeft="3dp"/>

    </LinearLayout>

    <!-- Title Of Song-->
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/thumbnail"
        android:layout_toRightOf="@+id/thumbnail"
        android:text="test"
        android:textColor="#040404"
        android:typeface="sans" 
        android:textSize="15dip"
        android:textStyle="bold"/>

    <!-- Artist Name -->

    <!-- Rightend Duration -->

     <!-- Rightend Arrow -->



    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_centerVertical="true"
        android:text="test"
        android:textColor="#040404"
        android:textSize="5dip"
        android:textStyle="bold"
        android:typeface="sans" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/thumbnail"
        android:layout_toRightOf="@+id/thumbnail"
        android:text="test"
        android:textColor="#040404"
        android:textSize="15dip"
        android:textStyle="bold"
        android:typeface="sans" />

</RelativeLayout>

/// Manifest

///

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.example"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".AutoCompleteTextViewActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
jason
  • 3,932
  • 11
  • 52
  • 123
  • 1
    return Spanned instead of "flat" String in your MatrixCursor – pskink Jan 30 '14 at 08:59
  • Hi Pskink.You had answered the same query before .Can you please look into this Please.Thanks for your time. – jason Jan 30 '14 at 09:02
  • Basically the above json query is myresult I get back from a database .How do I put that into autosuggestion .Also how do I place the link of the image in imageview ? – jason Jan 30 '14 at 09:05
  • 1
    c.newRow().add(i) .add(json.getString(i)); here first column is an int id and the second is String, you have to return Spanned instead of String – pskink Jan 30 '14 at 09:14
  • can you please edit it and show ? I am not getting it .Sorry for that. – jason Jan 30 '14 at 09:26
  • can you suggest any link to the above problem? I am not getting it. – jason Jan 30 '14 at 09:34
  • ok, i took a look and it seems that Cursor interface cannot return Spanned in any way, so, sorry... – pskink Jan 30 '14 at 09:43
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/46417/discussion-between-jason-and-pskink) – jason Jan 30 '14 at 10:18
  • btw my answer was for case where you need something like: "some text (image here) some other text (image here) yet another text". if you just want: "(image here) and some text here" the answer is **really** easy: use a layout with the ImageView and the TextView, no Spanned at all – pskink Jan 31 '14 at 11:49
  • Something on these lines http://i.dailymail.co.uk/i/pix/2011/08/11/article-2024574-0D63567000000578-432_306x458.jpg – jason Jan 31 '14 at 15:23

1 Answers1

1

ok try this:

    LinearLayout ll = new LinearLayout(this);
    ll.setOrientation(LinearLayout.VERTICAL);

    AutoCompleteTextView actv = new AutoCompleteTextView(this);
    actv.setThreshold(1);
    String[] from = {"name"};
    int[] to = {android.R.id.text1};
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_dropdown_item_1line, null, from, to) {

        // required for Spanned data
        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            MyCursor c = (MyCursor) cursor;
            TextView tv = (TextView) view;
            tv.setText(c.getSpanned());
        }

        // required for Spanned data
        @Override
        public CharSequence convertToString(Cursor cursor) {
            MyCursor c = (MyCursor) cursor;
            return c.getSpanned();
        }
    };
    FilterQueryProvider provider = new FilterQueryProvider() {
        @Override
        public Cursor runQuery(CharSequence constraint) {
            if (constraint == null) {
                return null;
            }
            MyCursor c = new MyCursor();
            // fake web service responses
            List<String> names = callFakeWebService(constraint);
            int i = 0;
            for (String name: names) {
                SpannableStringBuilder ssb = new SpannableStringBuilder(name);
                int start = name.indexOf(" ");
                ForegroundColorSpan what = new ForegroundColorSpan(0xffff0000);
                ssb.setSpan(what, start + 1, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                c.newRow().add(i++).add(name);
                c.addSpanned(ssb);
            }
            return c;
        }

        // fake web service request
        private List<String> callFakeWebService(CharSequence constraint) {
            Log.d(TAG, "callFakeWebService for: " + constraint);
            String[] namesArr = {
                    "Mark Smith",
                    "Monica Thompson",
                    "John White",
                    "Jane Brown"
            };
            String stringConstraint = constraint.toString().toLowerCase();
            List<String> names = new ArrayList<String>();
            for (int i = 0; i < namesArr.length; i++) {
                String name = namesArr[i];
                if (name.toLowerCase().startsWith(stringConstraint)) {
                    names.add(name);
                }
            }
            return names;
        }
    };
    adapter.setFilterQueryProvider(provider);
    actv.setAdapter(adapter);
    ll.addView(actv);
    TextView tv = new TextView(this);
    tv.setTextSize(32);
    tv.setTextColor(0xffff0000);
    tv.setText("type one of:\n  mark,\n  monica,\n  john\n  jane");
    ll.addView(tv);
    setContentView(ll);

where custom Cursor could look like this (it is minimalistic version supporting only one Spanned in a row):

static class MyCursor extends MatrixCursor {
    private static final String[] NAMES = {BaseColumns._ID, "name"};
    private ArrayList<Spanned> mSpannedList;

    public MyCursor() {
        super(NAMES);
        mSpannedList = new ArrayList<Spanned>();
    }

    public void addSpanned(Spanned s) {
        mSpannedList.add(s);
    }

    public Spanned getSpanned() {
        return mSpannedList.get(mPos);
    }
}

EDIT with no Spanned text:

    AutoCompleteTextView actv = new AutoCompleteTextView(this);
    actv.setThreshold(1);
    final String[] from = {BaseColumns._ID, "name", "artist", "title"};
    int[] to = {R.id.list_image, R.id.textView1, R.id.textView2, R.id.textView3};
    final SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.list_row, null, from, to);
    adapter.setStringConversionColumn(1);
    ViewBinder viewBinder = new ViewBinder() {
         public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
             if (columnIndex == 0) {
                 ImageView iv = (ImageView) view;
                 Bitmap bitmap = cursor.getExtras().getParcelable("image");
                 if (bitmap != null) {
                     iv.setImageBitmap(bitmap);
                 }
                 return true;
             }
             return false;
         }
    };
    adapter.setViewBinder(viewBinder);
    FilterQueryProvider provider = new FilterQueryProvider() {
        ExecutorService mPool = Executors.newCachedThreadPool();
        Uri URI = Uri.parse("adapter://autocomplete");

        public Cursor runQuery(CharSequence constraint) {
            if (constraint == null) {
                return null;
            }
            try {
                return callWebService(constraint, from);
            } catch (JSONException e) {
                e.printStackTrace();
                return null;
            }
        }

        // here you make the web request
        private Cursor callWebService(CharSequence constraint, String[] columnNames) throws JSONException {
            Log.d("TAG", "callWebService for: " + constraint);
            MatrixCursor cursor = new MyMatrixCursor(columnNames);

            // TODO do real network request
            // call web service here and keep the result in "jsonStr" 
            String jsonStr =  "{\"ResultArray\":[{\"data\":{ \"sno\":\"sno1\", \"date\":\"2011-08-21 14:27:09\", \"user\":\"1\", \"link\":\"http://scm-l3.technorati.com/11/11/17/56749/google-docs-revision.jpg?t=20111117074048\", \"name\":\"Aa\" }},{\"data\":{ \"sno\":\"sno2\", \"date\":\"2011-08-21 14:28:09\", \"user\":\"2\", \"link\":\"http://kcclaveria.com/wp-content/uploads/2013/02/google-panda-penguin.jpg\", \"name\":\"Bb\" }}]}";

            JSONObject json = new JSONObject(jsonStr);
            JSONArray resultArray = json.getJSONArray("ResultArray");

            int length = resultArray.length();
            for (int i = 0; i < length; i++) {
                JSONObject data = resultArray.getJSONObject(i).getJSONObject("data");

                cursor.newRow().add(i)
                    .add(data.getString("name"))
                    .add(data.getString("user"))
                    .add(data.getString("sno"));

                String link = data.getString("link");
                // get cached Bundle based on "link" (use HashMap<String, Bundle>)
                // or if new link initiate async request for getting the bitmap

                // TODO implement HashMap caching

                // new async request
                Bundle extras = new Bundle();
                try {
                    mPool.submit(new ImageRequest(link, extras));
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
                cursor.respond(extras);
            }
            cursor.setNotificationUri(getContentResolver(), URI);
            return cursor;
        }

        class ImageRequest implements Runnable {
            private URL mUrl;
            private Bundle mExtra;

            public ImageRequest(String link, Bundle extra) throws MalformedURLException {
                mUrl = new URL(link);
                mExtra = extra;
            }

            @Override
            public void run() {
                // TODO do real network request
                // simulate network delay
                Log.d(TAG, "getting " + mUrl);
                try {
                    Thread.sleep(2000 + (long) (4000 * Math.random()));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
                mExtra.putParcelable("image", b);
                getContentResolver().notifyChange(URI, null);
                Log.d(TAG, "run got a bitmap " + b.getWidth() + "x" + b.getHeight());
            }
        }
    };
    adapter.setFilterQueryProvider(provider);
    actv.setAdapter(adapter);

    LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    setContentView(actv, params);

and the custom MatrixCursor:

class MyMatrixCursor extends MatrixCursor {
    List<Bundle> mBundles = new ArrayList<Bundle>();

    public MyMatrixCursor(String[] columnNames) {
        super(columnNames);
    }

    @Override
    public Bundle respond(Bundle extras) {
        mBundles.add(extras);
        return extras;
    }

    @Override
    public Bundle getExtras() {
        return mBundles.get(mPos);
    }
}
pskink
  • 23,874
  • 6
  • 66
  • 77
  • Sorry pskink I never understood the above code to customize the way I want it .Is it possible to use the code I posted http://stackoverflow.com/questions/21475415/previous-data-is-entered-along-with-new-autocompletetextview .Can you please rewrite the code along the lines of the http given and imageview and textview.Sorry for the trouble>please look into it it will be of great help.Thanks. – jason Jan 31 '14 at 15:12
  • 1
    reading your other post it seeks that you dond need any image to be placed inside your TextFields so Spanned interface is not needed: you just want 3 TextViews and ImageView placed in some layout, right? if so read my update – pskink Jan 31 '14 at 15:46
  • yes exactly like his http://i.dailymail.co.uk/i/pix/2011/08/11/article-2024574-0D63567000000578-432_306x458.jpg – jason Jan 31 '14 at 15:48
  • which update ? the current post I am commenting on? But where is the imageview and other 3 textviews here ? – jason Jan 31 '14 at 15:50
  • yes this post, see EDIT, i use only one small ImageView and one TextView (found android's layout which has them, of course you should provide your custom layout) – pskink Jan 31 '14 at 16:14
  • `Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.RGB_565); bitmap.eraseColor(colors[i]);` this has to be replaced by "http images" .How do I do that ?The colors array is changed to http images.PLease have a look also I have posted the entire code with what I have in the main Question just now .PLease solve the above problem.The images currently have static links but I would be changing to dynamic after static starts to work.Please tell me how to make it work.Thanks again. – jason Jan 31 '14 at 19:31
  • Firstly thanks for your time and effort I really appreciate it .I am getting error in logcat and no image is appearing `Unable to decode stream: java.io.FileNotFoundException: /http:/www.google.com/trends/resources/2327917647-google-icon.png: open failed: ENOENT (No such file or directory) resolveUri failed on bad bitmap uri: http://www.google.com/trends/resources/2327917647-google-icon.png` – jason Feb 01 '14 at 12:07
  • 1
    FileNotFoundException: - no such resource on the server – pskink Feb 01 '14 at 12:18
  • I updated the links, In logcat I get::: `callWebService for: a getting https://www.google.org/crisisresponse/publicalerts/images/icons/google_search.png getting https://www.google.org/crisisresponse/publicalerts/images/icons/google_search.png run got a bitmap 64x64 run got a bitmap 64x64` also I dont still see the images in dropdown.Why so? – jason Feb 01 '14 at 12:36
  • I mean I get the ic_image_launcher icon the default_src image but not the image in that link. – jason Feb 01 '14 at 12:38
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/46592/discussion-between-jason-and-pskink) – jason Feb 01 '14 at 12:41
  • I tried a lot but am unable to solve the problem can you please even update that part of the code .Please Sir I am bad in atompletetextview methods.Thanks again. – jason Feb 01 '14 at 17:54
  • i dont know what you have done with my code because you didnt show your code – pskink Feb 01 '14 at 18:01
  • I have updated the code in the question.Please look into it.The image is not still displayed.I am posting main and list_row xml .PLease look into it. – jason Feb 01 '14 at 21:35
  • you can copy and paste the code it will work the same.PLease Sir look into it – jason Feb 01 '14 at 21:37
  • I have posted the entire code how to display the right image along with the text ? The text is appearing.Please make the image appear.Thanks for everything.I have been held up on this for a long time . – jason Feb 01 '14 at 22:47
  • CAn you please look into it .I have specified everything.I am unable to make it work. – jason Feb 02 '14 at 06:50
  • 1
    great! you made 95% of the job, now rhe images, hint: using android api uou need only 2 lines of code, with universal image loader just one line, remember remove Thread.sleep and use mUrl – pskink Feb 02 '14 at 07:17
  • I have updated the code with universal image loader in the Q.But still unable to see the image.Whats wrong here.Am I missing something.Please let me know or correct it if you can. – jason Feb 02 '14 at 12:16
  • Awesome its working now .Incredible.Finally after so long.This was tiring.Thanks a lot .+1 .Also how do I increase the size of row as the row is really small and it could get bigger – jason Feb 02 '14 at 12:25
  • 1
    you see it wasnt hard? if you use UIL dont use private URL mUrl, instead of it use private String mLink and use it for loadImageSync, you will have bigger images if you change maxWidth/maxHeight – pskink Feb 02 '14 at 12:56
  • Thank you Sir .I was just not understanding the part to set the imaageview .That was the problem,basically I did not know the viewholder in the above code.As you started suggesting I got the jist of the code.Thanks again for guiding me to the end of the code.It really was very important to me and urgent.I will get back to you if I have any queries .Thank you again.Have a Great Day. – jason Feb 02 '14 at 20:58
  • Please look into this http://stackoverflow.com/questions/21901281/autocompletetextview-layoutparams-is-covering-main-xml-fields .Unable to figure it out.Actually I am try to display pregressbar when its loading .Thanks – jason Feb 20 '14 at 07:54