When I was starting to recode Speech Timer for Android, I realised two things. One, the android tutorial in their website is too verbose for me. I need to read too many documents to get what I need. Second, the default Views of Android are not providing me what my application needs.
Well I have to say reading the introduction about how the Activity life cycle works is useful, and so is trying the Hello World and Hello Views tutorials. But besides that, I prefer to find the answer to my programming challenges from either stackoverflows.com or any other site which offers a question and answer mode. I find my productivity increases a lot. I mean, Google does present a pretty neat website to android development, but sometimes I am reading too many theory.
For this blog entry, I would like to discus about dynamic list generation. Android’s default implementation for ListView and ListActivity, are cumbersome for me. I cannot display it only as a part of a page, and I cannot load the content automatically if I use the XML showed in Android website’s tutorial. The tutorial only shows me that ListView is only applicable to a ListActivity, wherein the screen can only display a list, and the data for the list is expected to be static if I use the XML implementation.
For Speech Timer, I wanted to display two lists in a screen. The first screen will be dynamic, it will show a list of contacts whose name matches a pattern. The second list will display a list of speech types.
After some trial and error, I found the following code snippet suits me just well. The code below is to display the first list which is dynamic. It consists of several methods. The code to display the second list is simpler.
<!-- The XML part --> <EditText android:id="@+id/orator" android:layout_width="220dp" android:layout_alignParentTop="true" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_toRightOf="@id/oratorLabel" android:layout_height="wrap_content"/> <ScrollView android:id="@+id/scrollOrator" android:layout_width="fill_parent" android:layout_below="@id/orator" android:layout_marginTop="2dp" android:fadeScrollbars="false" android:layout_height="150dp"> <RelativeLayout android:id="@+id/oratorSection" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> </RelativeLayout> </ScrollView>
//The main onResume method protected void onResume(){ super.onResume(); this.setContentView(R.layout.select_speech); final ArrayList<String> sourceCt = getContactList(); linOrator = (RelativeLayout)findViewById(R.id.oratorSection); orator = (TextView)findViewById(R.id.orator); if(sourceCt!=null&&sourceCt.size()>0){ orator.setOnKeyListener(new OnKeyListener(){ @Override public boolean onKey(View v, int keyCode, KeyEvent event) { TextView tv = (TextView)v; ArrayList<String> fl = getFilterList(tv.getText().toString().trim(),sourceCt); displayFilteredContacts(fl); return false; } }); } } //Filtering the list private ArrayList<String> getFilterList(String searchStr,ArrayList<String> source){ //Only basic logic here, so no need to explain. You can do it. } //Getting the names from the contacts list private ArrayList <String> getContactList(){ ArrayList<String> contactData=new ArrayList<String>(); Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null); while (cursor.moveToNext()) { try{ String name=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); contactData.add(name); }catch(Exception e){ Toast.makeText(SelectSpeechActivity.this, "Failed getting contacts data.Please contact Basil Salad support", Toast.LENGTH_SHORT).show(); } } return contactData; } //Run this code if the user clicks on a row from the dynamic list private void selectOratorName(TextView t){ orator.setText(t.getText()); linOrator.removeAllViews(); } //The code to display the dynamic list private void displayFilteredContacts(ArrayList<String> filtered){ //In the beginning, always clear the list linOrator.removeAllViews(); //We will create each row dynamically int size = filtered.size(); for(int i=0;i<size;i++){ RelativeLayout innerLinLay = new RelativeLayout(this); innerLinLay.setId(22222*(i+1)); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.ALIGN_PARENT_LEFT); params.bottomMargin=3; if(i==0){ params.addRule(RelativeLayout.ALIGN_PARENT_TOP); }else{ params.addRule(RelativeLayout.BELOW, 22222*i); } innerLinLay.setLayoutParams(params); innerLinLay.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { TextView t = (TextView)r.getChildAt(0); selectOratorName(t); } }); TextView tv = new TextView(this); tv.setText(filtered.get(i)); tv.setTextColor(Color.BLACK); tv.setClickable(true); tv.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { selectOratorName(v); } }); RelativeLayout.LayoutParams tv1params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); tv1params.addRule(RelativeLayout.ALIGN_PARENT_TOP); tv.setGravity(Gravity.CENTER_VERTICAL); tv.setLayoutParams(tv1params); tv.setId(222+i); innerLinLay.addView(tv); /** The code to display the line, no need to explain it here */ linOrator.addView(innerLinLay); } //Always redraw the list at the end linOrator.refreshDrawableState(); }
0 thoughts on “Dynamic List – Android Development Tip”