首页 > 代码库 > ExpandableListView的使用以及信息的高亮显示
ExpandableListView的使用以及信息的高亮显示
ExpandableListView是ListView控件的延伸,它可以对数据进行分组显示和隐藏,并统计总数量;可进行滚动,对某一内容高亮显示。
<1>编写xml布局文件,用于获取ExpandableListView对象
sf_activity_contact_list.xml
<span style="font-family:Microsoft YaHei;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/contacts_list_holder" style="@style/SF_ActivityBackground" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/sf_activity_background_color" android:overScrollMode="always" android:scrollbarStyle="outsideInset" android:scrollbars="vertical"> <!-- style="@style/SF_ActivityBackground" --> <ExpandableListView android:id="@+id/contacts_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:fastScrollEnabled="true" > </ExpandableListView> </LinearLayout></span>
<2>编写Activity界面,获取ExpandableListView对象,并设置适配器和相应的属性、事件等等
package com.snapfish.ui; import java.util.ArrayList; import java.util.List; import org.json.JSONException; import org.json.JSONObject; import android.app.AlertDialog; import android.app.SearchManager; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.graphics.PixelFormat; import android.os.Bundle; import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.SearchView; import android.support.v7.widget.SearchView.OnQueryTextListener; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.EditText; import android.widget.ExpandableListView; import android.widget.ExpandableListView.OnChildClickListener; import android.widget.ImageView; import android.widget.TextView; import com.snapfish.R; import com.snapfish.android.generated.bean.AddressType; import com.snapfish.android.generated.bean.Entry; import com.snapfish.android.generated.bean.MrchShippingOption; import com.snapfish.android.generated.bean.OpenSocialResponseType; import com.snapfish.android.generated.bean.Person; import com.snapfish.android.generated.bean.PublisherOrder; import com.snapfish.android.generated.bean.PublisherOrderAddress; import com.snapfish.checkout.IUserData; import com.snapfish.internal.core.SFConstants; import com.snapfish.internal.database.SFContactsHolderDB; import com.snapfish.internal.datamodel.SFContact; import com.snapfish.internal.datamodel.SFContactDBManager; import com.snapfish.internal.event.SFEventManager; import com.snapfish.internal.event.SFIEventListener; import com.snapfish.internal.event.SFLocaleContactsEvent; import com.snapfish.internal.event.SFRemoteContactsEvent; import com.snapfish.util.CShippingOptionsAdapter; import com.snapfish.util.SFActivityUtils; import com.snapfish.util.SFContactExpandableListAdapter; import com.snapfish.util.SFLogger; public class SFContactsListActivity extends ABaseActivity { // implements // LoaderManager.LoaderCallbacks<Cursor> private static final SFLogger sLogger = SFLogger .getInstance(SFContactsListActivity.class.getName()); private Context m_ctx; private TextView m_contactNameOverlay; private boolean m_visible; // private static final int CONTACT_DATA_LOADER = 111; OnScrollListener mItemsListScrollListener = new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { m_visible = true; // when stop scrolling if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) { m_contactNameOverlay.setVisibility(View.INVISIBLE); m_visible = false; } // when scrolling and the finger is on the screen else if (scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { } // when scrolling and the finger perform an action above else if (scrollState == OnScrollListener.SCROLL_STATE_FLING) { } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (visibleItemCount > 0 && m_visible) { SFContact contact = mPhoneContacts.get(firstVisibleItem); m_contactNameOverlay.setText(String.valueOf(contact.getName() .charAt(0))); m_contactNameOverlay.setVisibility(View.VISIBLE); } } }; /************************************************** * The event of getting locale contacts *************************************************/ private SFIEventListener<SFLocaleContactsEvent> m_localeContactListEvent = new SFIEventListener<SFLocaleContactsEvent>() { @Override public void onEvent(SFLocaleContactsEvent event) { // TODO The event of getting locale contacts sLogger.debug("****************The event of getting locale contacts*****************"); hideProgressDialog(); if (null != event && event.getContactsList() != null) { mPhoneContacts = event.getContactsList(); showProgressDialog(getString(R.string.sf_please_wait), getString(R.string.sf_progress_remote_contact_list)); // Get all remote contacts SFContactDBManager.asyncGetAllRemoteContacts(getSession()); } } }; /************************************************** * The event of getting remote contacts *************************************************/ private SFIEventListener<SFRemoteContactsEvent> m_remoteContactListEvent = new SFIEventListener<SFRemoteContactsEvent>() { @Override public void onEvent(SFRemoteContactsEvent event) { // TODO The event of getting remote contacts sLogger.debug("****************The event of getting remote contacts*****************"); hideProgressDialog(); if (null != event && event.getOpenSocialResponseType() != null) { OpenSocialResponseType osrt = event.getOpenSocialResponseType(); if (null != osrt) { List<Entry> entries = osrt.getEntryList(); if (null != entries && !entries.isEmpty()) { int entrySize = entries.size(); for (int i = 0; i < entrySize; i++) { try { Person person = Person.newFromJSON(entries.get( i).toJSON()); if (null != person) { AddressType address = person.getAddress(); String displayName = person .getDisplayName(); if (isValidContact(address) && !TextUtils.isEmpty(displayName)) { SFContact contact = new SFContact( IUserData.EUserDataType.SNAPFISH, person.getId(), displayName, address.getStreet1(), address.getCity(), address.getProvince(), address.getPostalCode(), SFContact.ContactAddressType.TYPE_OTHER); contact.setGuessedPrecision(SFContact.GuessedPrecision.ABSOLUTE); contact.setCountry(address.getCountry() == null ? getResources() .getConfiguration().locale .getCountry() : address .getCountry()); contact.setAddressGuessed(false); contact.setIsConfirmed(true); contact.setPhone(address.getPhone()); mPhoneContacts.add(contact); } } } catch (JSONException e) { sLogger.error(e.getMessage()); } } } } } onContactsListCreated(); } }; /* * carry over from order review activity in case if contact has to be edited * or order update must happen on this screen */ private PublisherOrder m_publisherOrder; private int m_orderQuantity; private long m_mrchId; private SFContact mSelectedAddress; private List<SFContact> mPhoneContacts; private ExpandableListView mContactsListView; private SFContactExpandableListAdapter mContactsListAdapter; private List<MrchShippingOption> m_mrchShippingOptions = new ArrayList<MrchShippingOption>(); private String m_shippingOptionDesc; private String m_shippingOptionType; /* search */ private MenuItem searchItem; private SearchView mSearchView; private ImageView closeBtn; private EditText searchEditText; public static boolean isSearchQuery; private String mSearchString; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.sf_activity_contact_list); m_ctx = this; // getSupportLoaderManager().initLoader(CONTACT_DATA_LOADER, null, // this); // Display home and finish current activity SFActivityUtils.displayHomeAsUp(this); getDataFromIntent(); mContactsListView = (ExpandableListView) findViewById(R.id.contacts_list); /* * on child click the action that happens will depend whether contact * selected is confirmed or not, meaning that the end-user has validated * address and order can be safely sent to selected address */ mContactsListView.setOnChildClickListener(new OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { mSelectedAddress = (SFContact) mContactsListAdapter.getChild( groupPosition, childPosition); /* * in the event when address precision is below 100% it must be * validated by the end-user so the CShippingAddressActivity is * launched first */ Intent exitIntent = null; if (mSelectedAddress.getGuessedPrecision() != SFContact.GuessedPrecision.ABSOLUTE) { exitIntent = new Intent(SFContactsListActivity.this, SFShippingAddressActivity.class); /* pass contact _id */ exitIntent.putExtra( SFContactsHolderDB.SFContactColumns._ID, mSelectedAddress.getId()); /* selected shipping address for edit */ exitIntent.putExtra(SFConstants.SF_SHIPPING_ADDRESS, handleLocalization(mSelectedAddress)); /* shipping options */ exitIntent.putExtra( SFConstants.MRCH_SHIP_OPTIONS, getIntent().getStringArrayExtra( SFConstants.MRCH_SHIP_OPTIONS)); /* order ID ? */ exitIntent.putExtra(SFConstants.ORDERID, m_publisherOrder.getOrderId()); /* quantity ? */ exitIntent.putExtra(SFConstants.ORDER_QUANTITY, getIntent() .getIntExtra(SFConstants.ORDER_QUANTITY, -1)); /* mrchId */ exitIntent.putExtra(SFConstants.MRCH_ID, getIntent() .getLongExtra(SFConstants.MRCH_ID, -1)); /* and finally order */ exitIntent.putExtra(SFConstants.SF_ORDER, orderAsString()); startActivityForResult(exitIntent, SFConstants.SF_REQUEST_CODE_SHIPPING_ADDRESS); } else {/* adding selected address to order */ m_publisherOrder.setShippingAddress(mSelectedAddress); resetShippingOptions(); if (m_shippingOptionDesc != null && m_shippingOptionType != null) { exitIntent = new Intent(); exitIntent.putExtra(SFConstants.SF_ORDER, orderAsString()); exitIntent.putExtra( SFConstants.SF_SHIPPING_OPTION_DESCRIPTION, m_shippingOptionDesc); exitIntent.putExtra( SFConstants.SF_SHIPPING_OPTION_SHIPPING_TYPE, m_shippingOptionType); setResult(RESULT_OK, exitIntent); finish(); } } return false; } }); } @Override protected void onResume() { // register the event of getting locale contacts SFEventManager.subscribe(m_ctx, SFLocaleContactsEvent.class, m_localeContactListEvent); // register the event of getting remote contacts SFEventManager.subscribe(m_ctx, SFRemoteContactsEvent.class, m_remoteContactListEvent); m_contactNameOverlay = (TextView) LayoutInflater.from(m_ctx).inflate( R.layout.sf_contact_pop_overlay, null); m_contactNameOverlay.setVisibility(View.INVISIBLE); WindowManager.LayoutParams lp = new WindowManager.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT); WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); windowManager.addView(m_contactNameOverlay, lp); showProgressDialog(getString(R.string.sf_please_wait), getString(R.string.sf_progress_locale_contact_list)); // Get all local contacts SFContactDBManager.asyncGetAllLocalContacts(getSession()); // initializeData(); // ctx = this; // mContactsListView.setAdapter(new ContactExpandListAdapter(group, // child, ctx)); super.onResume(); } @Override protected void onPause() { // uninstall the event of getting locale contacts SFEventManager.unsubscribe(m_ctx, SFLocaleContactsEvent.class, m_localeContactListEvent); // uninstall the event of getting remote contacts SFEventManager.unsubscribe(m_ctx, SFRemoteContactsEvent.class, m_remoteContactListEvent); super.onPause(); } /** * simply copies street1 into street2 whenever street2 is a mandatory field * in the address entry * * @param contact * @return */ private String handleLocalization(PublisherOrderAddress contact) { if (getResources().getBoolean(R.bool.sf_address_street2_required)) { sLogger.debug("not a localized address: " + contact.toString()); if (contact.getStreet2() == null) { contact.setStreet2(contact.getStreet1()); contact.setStreet1(null); } } String convertedAddr = ""; try { convertedAddr = contact.toJSON().toString(); sLogger.debug("localized address: " + convertedAddr); } catch (JSONException e) { sLogger.error("cannot convert selected address: " + e); } return convertedAddr; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == SFConstants.SF_REQUEST_CODE_SHIPPING_ADDRESS) { if (resultCode == RESULT_OK) { /* * after a contact had been verified by end-user it's precision * level is moved to ABSOLUTE */ mSelectedAddress .setGuessedPrecision(SFContact.GuessedPrecision.ABSOLUTE); setResult(RESULT_OK, data); finish(); } } } /** * carry over the data required by CShippingAddressActivity */ private void getDataFromIntent() { Intent intent = getIntent(); String order = intent.getStringExtra(SFConstants.SF_ORDER); String[] mrchShippingOptions = getIntent().getStringArrayExtra( SFConstants.MRCH_SHIP_OPTIONS); if (order != null) { try { m_publisherOrder = PublisherOrder.newFromJSON(new JSONObject( order)); if (null != mrchShippingOptions) { for (String mrchShippingOption : mrchShippingOptions) { m_mrchShippingOptions .add(MrchShippingOption .newFromJSON(new JSONObject( mrchShippingOption))); } } } catch (JSONException e) { sLogger.error("cannot parse order: " + order); sLogger.error("cannot parse order: " + e); } } else { showWarningDialog("Order failed", "order not found in intent"); } } /** * initializes the contacts list adapter */ private void onContactsListCreated() { /* set adapter */ mContactsListAdapter = new SFContactExpandableListAdapter(this, mPhoneContacts); mContactsListView.setAdapter(mContactsListAdapter); /* hide the divider */ mContactsListView.setDivider(null); /* * hide indicator, by design it's the first letter of a contact that * takes place of the indicator */ mContactsListView.setGroupIndicator(null); /* * make list state expanded - the first time it should display expanded * list of contacts */ for (int i = 0; i < mContactsListAdapter.getGroupCount(); i++) { mContactsListView.expandGroup(i); } /* * onScrollListener */ mContactsListView.setOnScrollListener(mItemsListScrollListener); } // private List<String> group;// 组列表 // private List<List<String>> child;// 子列表 // private Context ctx; // // private void initializeData() { // group = new ArrayList<String>(); // child = new ArrayList<List<String>>(); // // addInfo("Andy", new String[] { "male", "138123***", "GuangZhou" }); // addInfo("Fairy", new String[] { "female", "138123***", "GuangZhou" }); // addInfo("Jerry", new String[] { "male", "138123***", "ShenZhen" }); // addInfo("Tom", new String[] { "female", "138123***", "ShangHai" }); // addInfo("Bill", new String[] { "male", "138231***", "ZhanJiang" }); // } // // private void addInfo(String group, String[] child) { // this.group.add(group); // List<String> childItem = new ArrayList<String>(); // for (int i = 0; i < child.length; i++) { // childItem.add(child[i]); // } // // this.child.add(childItem); // } /** * converts order to string * * @return */ private String orderAsString() { String orderAsString = ""; try { orderAsString = m_publisherOrder.toJSON().toString(); } catch (JSONException e) { e.printStackTrace(); } return orderAsString; } private void resetShippingOptions() { PublisherOrder order = m_publisherOrder; PublisherOrderAddress cnt = null; try { cnt = PublisherOrderAddress.newFromJSON(new JSONObject( handleLocalization(order.getShippingAddress()))); sLogger.debug("order address: " + cnt.toJSON()); } catch (JSONException e) { e.printStackTrace(); } if (m_mrchShippingOptions.size() > 0) { CShippingOptionsAdapter soa = new CShippingOptionsAdapter( getApplicationContext(), getSession().getAppCredentials() .getLocale(), m_mrchShippingOptions, m_mrchId, m_orderQuantity, cnt); String shipping = getApplicationContext().getResources().getString( R.string.sf_order_shipping_opt_no_colon); sLogger.debug("getSession().getAppCredentials().getLocale(): " + getSession().getAppCredentials().getLocale()); sLogger.debug("soa.getAvailableShipOptions().size(): " + soa.getAvailableShipOptions().size()); if (soa.getAvailableShipOptions().size() > 0) { MrchShippingOption item = soa.getAvailableShipOptions().get(0); String shippingDescription = item.getDescription(); String shippingType = Character.toString( shippingDescription.charAt(0)).toUpperCase() + shippingDescription.substring(1); order.setShippingOption(item.getShippingCode()); order.setShipping(0.0f); m_shippingOptionDesc = soa.estimatedDeliveryDays(item .getShippingCode()); m_shippingOptionType = shippingType + shipping; showProgressDialog( getResources().getString(R.string.sf_please_wait), getResources().getString( R.string.sf_progress_update_order)); } else { showErrorAlertDialog(); } } } private void showErrorAlertDialog() { AlertDialog.Builder alertDialog = new AlertDialog.Builder( SFContactsListActivity.this); alertDialog.setTitle(R.string.sf_warning_dialog_title); alertDialog.setMessage(R.string.sf_error_no_shipping_options) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).show(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.sf_menu_p2r, menu); searchItem = menu.findItem(R.id.p2r_action_search); mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem); searchEditText = (EditText) mSearchView .findViewById(R.id.search_src_text); searchEditText.setHintTextColor(getResources().getColor( R.color.sf_button_normal)); searchEditText.setHint(R.string.sf_contacts_search_hint); SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); ComponentName searchComponent = new ComponentName(this, SFContactsListActivity.class); mSearchView.setSearchableInfo(searchManager .getSearchableInfo(searchComponent)); mSearchView.setIconifiedByDefault(true); mSearchView.setSubmitButtonEnabled(false); closeBtn = (ImageView) mSearchView.findViewById(R.id.search_close_btn); MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() { @Override public boolean onMenuItemActionCollapse(MenuItem arg0) { sLogger.debug("search field collapsed"); return true; } @Override public boolean onMenuItemActionExpand(MenuItem arg0) { sLogger.debug("search field expanded"); return true; } }); closeBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { searchEditText.setText(""); } }); mSearchView.setOnQueryTextListener(new OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String arg0) { return false; } @Override public boolean onQueryTextChange(String searchText) { if (searchText.length() > 0) { mSearchString = searchText; sLogger.debug("search text is: " + searchText); } else { mSearchString = null; sLogger.debug("reset list"); } return true; } }); return super.onCreateOptionsMenu(menu); } /** * Invoking this method when the item option of menu selected */ @Override public boolean onOptionsItemSelected(MenuItem item) { // when the top|left icon selected,finish current activity if (item.getItemId() == android.R.id.home) { finish(); overridePendingTransition(R.anim.fade_in, R.anim.fade_out); return true; } return super.onOptionsItemSelected(item); } private boolean isValidContact(AddressType addressType) { if (addressType == null) return false; if (!TextUtils.isEmpty(addressType.getStreet1()) && !TextUtils.isEmpty(addressType.getCity()) && !TextUtils.isEmpty(addressType.getProvince()) && !TextUtils.isEmpty(addressType.getPhone())) return true; return false; } }
<3>编写布局文件sf_view_contact_sort_header.xml,用于展示租名和记录数量。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:paddingTop="5dp" android:paddingBottom="5dp" android:paddingLeft="@dimen/sf_standard_layout_padding" android:paddingRight="@dimen/sf_standard_layout_padding" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/sf_contact_sort_by_name" style="@style/SF_MediumBlueBoldTxt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:layout_marginLeft="5dp" android:text="@string/sf_contacts_sorting_txt" /> <TextView android:id="@+id/sf_contact_sort_counter" style="@style/SF_SmallLightGreyTxt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:gravity="right" android:text="@string/sf_contacts_counter_txt" android:visibility="gone" /> </RelativeLayout>
<4>编写布局文件sf_view_contact_item.xml,用于展示数据的内容:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/SF_SelectableSectionBackground" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/sf_activity_background_color" android:paddingBottom="5dp" android:paddingLeft="@dimen/sf_contact_item_layout_padding" android:paddingRight="@dimen/sf_contact_item_layout_padding" > <LinearLayout android:id="@+id/sf_ll_contact_item_divider" style="@style/SF_HorizontalDivider" android:layout_width="match_parent" android:layout_marginBottom="5dp" android:orientation="horizontal" /> <include android:id="@+id/sf_include_contact_item_photo" android:layout_width="65dp" android:layout_height="65dp" android:layout_alignLeft="@+id/sf_ll_contact_item_divider" android:layout_alignTop="@+id/sf_ll_contact_item_divider" android:layout_centerHorizontal="true" android:layout_centerInParent="true" android:layout_centerVertical="true" android:layout_marginTop="5dp" layout="@layout/sf_view_contact_graphics" android:visibility="visible" /> <LinearLayout android:id="@+id/sf_ll_contact_item_details" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_marginTop="5dp" android:layout_toRightOf="@id/sf_include_contact_item_photo" android:gravity="left|center_horizontal" android:orientation="vertical" > <!-- name --> <TextView android:id="@+id/sf_tv_contact_item_name" style="@style/SF_MediumBlackTxt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:ellipsize="end" android:singleLine="true" android:text="@string/sf_name_placeholder" /> <!-- name end --> <!-- address --> <TextView android:id="@+id/sf_tv_contact_item_address" style="@style/SF_SmallGreyTxt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:ellipsize="end" android:singleLine="false" android:text="@string/sf_address_placeholder" android:textAlignment="center" /> <!-- address end --> <TextView android:id="@+id/sf_tv_contact_item_phone" style="@style/SF_MediumLightGreyTxt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:minLines="1" android:scrollHorizontally="false" android:singleLine="true" android:text="@string/sf_adress_type_txt" android:visibility="gone" /> </LinearLayout> </RelativeLayout>
<5>编写SFContactExpandableListAdapter.java,继承BaseExpandableListAdapter.java
package com.snapfish.util; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import android.annotation.SuppressLint; import android.content.ContentUris; import android.content.Context; import android.content.res.Resources; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.net.Uri; import android.provider.ContactsContract.Contacts; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.snapfish.R; import com.snapfish.checkout.IUserData; import com.snapfish.internal.datamodel.SFContact; import com.snapfish.ui.SFContactsListActivity; public class SFContactExpandableListAdapter extends BaseExpandableListAdapter { // implements // LoaderManager.LoaderCallbacks<Cursor> private static final SFLogger sLogger = SFLogger .getInstance(SFContactsListActivity.class.getName()); private Context m_ctx; private ViewHolder m_viewHolder; private List<SFContact> mCombinedContacts; private Map<String, List<SFContact>> mSortedContacts; public SFContactExpandableListAdapter(Context mContext, List<SFContact> mCombinedContacts) { this.m_ctx = mContext; this.mCombinedContacts = mCombinedContacts; this.mSortedContacts = getSortedContacts(); m_viewHolder = new ViewHolder(); } @Override public int getGroupCount() { return mSortedContacts.size(); } @Override public int getChildrenCount(int groupPosition) { List<SFContact> children = mSortedContacts .get(getKeyByPosition(groupPosition)); return children.size(); } @Override public Object getGroup(int groupPosition) { List<SFContact> group = mSortedContacts .get(getKeyByPosition(groupPosition)); return group; } @Override public Object getChild(int groupPosition, int childPosition) { @SuppressWarnings("unchecked") List<SFContact> selectedGroup = (List<SFContact>) getGroup(groupPosition); if (selectedGroup.size() < childPosition) return null; return selectedGroup.get(childPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @SuppressWarnings("unchecked") @Override public long getChildId(int groupPosition, int childPosition) { List<SFContact> childGroup = (List<SFContact>) getGroup(groupPosition); if (null != childGroup && childGroup.get(childPosition) != null) return childPosition; return 0; } @Override public boolean hasStableIds() { return false; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { View row = LayoutInflater.from(m_ctx).inflate( R.layout.sf_view_contact_sort_header, parent, false); TextView sortTextView = (TextView) row .findViewById(R.id.sf_contact_sort_by_name); TextView countTextView = (TextView) row .findViewById(R.id.sf_contact_sort_counter); String letter = getKeyByPosition(groupPosition); if (groupPosition == 0) { countTextView.setVisibility(View.VISIBLE); countTextView.setText("" + mCombinedContacts.size() + " " + m_ctx.getString(R.string.sf_contacts_counter_txt)); } sortTextView.setText(" " + letter); return row; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { SFContact contact = (SFContact) getChild(groupPosition, childPosition); if (contact != null) { // SFContact.ContactAddressType displayType = contact // .getAddressType(); String displayName = contact.getName(); String displayAddress = getContactAddress(contact); View row = LayoutInflater.from(m_ctx).inflate( R.layout.sf_view_contact_item, parent, false); // contact name m_viewHolder.m_name = (TextView) row .findViewById(R.id.sf_tv_contact_item_name); m_viewHolder.m_name.setText(displayName); // contact address m_viewHolder.m_address = (TextView) row .findViewById(R.id.sf_tv_contact_item_address); m_viewHolder.m_address.setText(displayAddress); /* contact address type */ m_viewHolder.m_phone = (TextView) row .findViewById(R.id.sf_tv_contact_item_phone); // contact photo setContactIcon(row, contact, getKeyByPosition(groupPosition)); // if (isMultipleAddress(groupPosition, childPosition) // || contact.getGuessedPrecision() == // SFContact.GuessedPrecision.LOW) { // showAddressType(m_viewHolder.m_phone, // contact.getGuessedPrecision(), displayType); // } row.setTag(m_viewHolder); return row; } return convertView; } /** * to avoid displaying address type when we do not have matching contacts * * @param groupPosition * @param childPosition * @return */ private boolean isMultipleAddress(int groupPosition, int childPosition) { @SuppressWarnings("unchecked") List<SFContact> group = (List<SFContact>) getGroup(groupPosition); SFContact reference = (SFContact) getChild(groupPosition, childPosition); String referenceName = reference.getName(); int i = group.size(); for (int a = 0; a < i; a++) { if (a != childPosition) if (referenceName.equalsIgnoreCase(group.get(a).getName())) return true; } return false; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } /** * contact icons are of three kinds: image, icon, or warning message * * @param aContact * @param letter * @param addrPositiveMatch */ private void setContactIcon(View row, SFContact aContact, String letter) { // TODO guessed precision was not set in the DB - set it up SFContact.GuessedPrecision addrPositiveMatch = aContact .getGuessedPrecision(); ViewGroup contactImageView = (ViewGroup) row .findViewById(R.id.sf_include_contact_item_photo); if (contactImageView != null) { ImageView unverifiedAddress = (ImageView) contactImageView .findViewById(R.id.sf_iv_contact_need_confirmation); LinearLayout noCntPhoto = (LinearLayout) contactImageView .findViewById(R.id.sf_ll_contact_no_photo); TextView cntFirstLetter = (TextView) noCntPhoto .findViewById(R.id.sf_tv_contact_name_letter); ImageView defaultCntIcon = (ImageView) contactImageView .findViewById(R.id.sf_iv_contact_default_photo); defaultCntIcon.setVisibility(View.GONE); cntFirstLetter.setVisibility(View.GONE); noCntPhoto.setVisibility(View.GONE); /* get profile photo bitmap to load into ImageView */ Bitmap bmp = getProfilePhoto(aContact); switch (addrPositiveMatch) { case ABSOLUTE: if (bmp != null) { defaultCntIcon.setVisibility(View.VISIBLE); defaultCntIcon.setImageBitmap(bmp); } else { noCntPhoto.setVisibility(View.VISIBLE); noCntPhoto.setBackgroundColor(Color .parseColor(getRandomColor())); cntFirstLetter.setVisibility(View.VISIBLE); cntFirstLetter.setText(letter); } break; case HIGH: unverifiedAddress.setVisibility(View.VISIBLE); break; case MEDIUM: unverifiedAddress.setVisibility(View.VISIBLE); break; case LOW: break; default: unverifiedAddress.setVisibility(View.VISIBLE); break; } } } private void showAddressType(TextView typeView, SFContact.GuessedPrecision precisionLevel, SFContact.ContactAddressType displayType) { Resources r = m_ctx.getResources(); // typeView.setVisibility(View.VISIBLE); typeView.setVisibility(View.GONE); if (precisionLevel != SFContact.GuessedPrecision.ABSOLUTE) {// not // verified // (guessed) // address typeView.setTextColor(r .getColor(R.color.sf_error_message_txt_color)); typeView.setText(r.getString(R.string.sf_verify_address_label)); } else if (displayType != null) { // verified address typeView.setText(getAddressType(displayType)); } } private int colorsUsed; /** * using preset swatches to set background colors in the layout * * @return */ private String getRandomColor() { String[] colorChoises = m_ctx.getResources().getStringArray( R.array.sf_swatches_sp_set); if (colorsUsed == colorChoises.length) colorsUsed = 0; String colorOut = colorChoises[colorsUsed]; colorsUsed++; return colorOut; } private Bitmap getProfilePhoto(SFContact aContact) { if (aContact.getContactSource().equals( IUserData.EUserDataType.PHONEBOOK)) { InputStream photoStream = getPhotoAsInputSteam(aContact); if (photoStream != null) return BitmapFactory.decodeStream(photoStream); } return null; } private String getKeyByPosition(int groupPosition) { int keyPosition = 0; Iterator<String> iter = mSortedContacts.keySet().iterator(); while (iter.hasNext()) { String key = iter.next(); if (keyPosition == groupPosition) { return key; } keyPosition++; } return null; } /** * extracting first letter of display name * * @return */ private Collection<String> extractFirstLetter() { Collection<String> sortByLetter = new HashSet<String>(); int index = mCombinedContacts.size(); Collections.sort(mCombinedContacts, new Comparator<SFContact>() { @Override public int compare(SFContact lhs, SFContact rhs) { return lhs.getName().compareTo(rhs.getName()); } }); for (int i = 0; i < index; i++) { char letter = mCombinedContacts.get(i).getName().charAt(0); sortByLetter.add(String.valueOf(letter).toUpperCase()); } return sortByLetter; } private Map<String, List<SFContact>> getSortedContacts() { List<SFContact> selectedContact = null; mSortedContacts = new TreeMap<String, List<SFContact>>(); Iterator<String> firstLetter = extractFirstLetter().iterator(); while (firstLetter.hasNext()) { String s = firstLetter.next(); int index = mCombinedContacts.size(); selectedContact = new ArrayList<SFContact>(); for (int i = 0; i < index; i++) { String initChar = String.valueOf(mCombinedContacts.get(i) .getName().charAt(0)); if (s.equalsIgnoreCase(initChar)) { selectedContact.add(mCombinedContacts.get(i)); } } mSortedContacts.put(s, selectedContact); } return mSortedContacts; } /** * retrieves address type string from arrays.xml * * @param addressType * @return */ private String getAddressType(SFContact.ContactAddressType addressType) { String addrTypeOut = ""; int arrSize = m_ctx.getResources().getStringArray( R.array.sf_address_type).length; if (arrSize != 0 && arrSize == 3) { switch (addressType) { case TYPE_HOME: addrTypeOut = m_ctx.getResources().getStringArray( R.array.sf_address_type)[0]; break; case TYPE_WORK: addrTypeOut = m_ctx.getResources().getStringArray( R.array.sf_address_type)[1]; break; case TYPE_OTHER: default: addrTypeOut = m_ctx.getResources().getStringArray( R.array.sf_address_type)[2]; break; } } else addrTypeOut = "UNKNOWN"; return addrTypeOut; } private InputStream getPhotoAsInputSteam(SFContact contact) { byte[] data = http://www.mamicode.com/contact.getContactPhotoData();>
注意
继承BaseExpandableListAdapter需实现相应的方法:<1>getGroupId():获取组号
<2>getChildId():获取子元素编号(位于组中)
<3>getGroup():获取指定组的组内容
<4>getChild():根据组和子元素的位置获取子元素内容
<5>getGroupCount():获取组的数目
<6>getChildrenCount():获取对应组的子元素的数目
<7>getGroupView():获取View对象用于显示组内容
<8>getChildView():根据组和子元素的位置获取View对象用于显示子元素的内容
<9>hasStableIds():组和子元素是否持有稳定的ID,也就是底层数据的改变不会影响到它们
<10>isChildSelectable():是否可选择指定位置的子元素
ExpandableListView的使用以及信息的高亮显示
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。