仿Iphone中搜索结果的布局详解
本篇文章是对仿Iphone中搜索结果的布局进行了详细的分析介绍,需要的朋友参考下
代码如下:
public class Search extends LinearLayout
implements OnClickListener, OnKeyListener, OnLongClickListener, OnItemClickListener {
// Speed at which the widget slides up/down, in pixels/ms.
private static final float ANIMATION_VELOCITY = 1.0f;
/** The distance in dips between the optical top of the widget and the top if its bounds */
private static final float WIDGET_TOP_OFFSET = 9;
private final String TAG = "SearchWidget";
private Launcher mLauncher;
private EditText mSearchText;
private ImageButton mVoiceButton;
private ImageButton mClearButton;
/** The animation that morphs the search widget to the search dialog. */
private Animation mMorphAnimation;
/** The animation that morphs the search widget back to its normal position. */
private Animation mUnmorphAnimation;
// These four are passed to Launcher.startSearch() when the search widget
// has finished morphing. They are instance variables to make it possible to update
// them while the widget is morphing.
private String mInitialQuery;
private boolean mSelectInitialQuery;
private Bundle mAppSearchData;
private boolean mGlobalSearch;
ListView mSearchResultList=null;
LinearLayout mSearchResult=null;
// For voice searching
private Intent mVoiceSearchIntent;
private int mWidgetTopOffset;
private int mAlpha = 0xff;//2011-01-12 add for draw alpha
private ArrayList<Map<String, Object>> mData;
private LockScreenAdapter mAdapter;
private List<Info> dataList;
private Context mContext;
private static final String[] ALL_THREADS_PROJECTION = {
Threads._ID, Threads.DATE, Threads.MESSAGE_COUNT, Threads.RECIPIENT_IDS,
Threads.SNIPPET, Threads.SNIPPET_CHARSET, Threads.READ, Threads.ERROR,
Threads.HAS_ATTACHMENT
};
private static final Uri sAllThreadsUri =
Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build();
/**
* Used to inflate the Workspace from XML.
*
* @param context The application's context.
* @param attrs The attributes set containing the Workspace's customization values.
*/
public Search(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
final float scale = context.getResources().getDisplayMetrics().density;
mWidgetTopOffset = Math.round(WIDGET_TOP_OFFSET * scale);
Interpolator interpolator = new AccelerateDecelerateInterpolator();
mMorphAnimation = new ToParentOriginAnimation();
// no need to apply transformation before the animation starts,
// since the gadget is already in its normal place.
mMorphAnimation.setFillBefore(false);
// stay in the top position after the animation finishes
mMorphAnimation.setFillAfter(true);
mMorphAnimation.setInterpolator(interpolator);
mMorphAnimation.setAnimationListener(new Animation.AnimationListener() {
// The amount of time before the animation ends to show the search dialog.
private static final long TIME_BEFORE_ANIMATION_END = 80;
// The runnable which we'll pass to our handler to show the search dialog.
private final Runnable mShowSearchDialogRunnable = new Runnable() {
public void run() {
showSearchDialog();
}
};
public void onAnimationEnd(Animation animation) { }
public void onAnimationRepeat(Animation animation) { }
public void onAnimationStart(Animation animation) {
// Make the search dialog show up ideally *just* as the animation reaches
// the top, to aid the illusion that the widget becomes the search dialog.
// Otherwise, there is a short delay when the widget reaches the top before
// the search dialog shows. We do this roughly 80ms before the animation ends.
getHandler().postDelayed(
mShowSearchDialogRunnable,
Math.max(mMorphAnimation.getDuration() - TIME_BEFORE_ANIMATION_END, 0));
}
});
mUnmorphAnimation = new FromParentOriginAnimation();
// stay in the top position until the animation starts
mUnmorphAnimation.setFillBefore(true);
// no need to apply transformation after the animation finishes,
// since the gadget is now back in its normal place.
mUnmorphAnimation.setFillAfter(false);
mUnmorphAnimation.setInterpolator(interpolator);
mUnmorphAnimation.setAnimationListener(new Animation.AnimationListener(){
public void onAnimationEnd(Animation animation) {
clearAnimation();
}
public void onAnimationRepeat(Animation animation) { }
public void onAnimationStart(Animation animation) { }
});
mVoiceSearchIntent = new Intent(android.speech.RecognizerIntent.ACTION_WEB_SEARCH);
mVoiceSearchIntent.putExtra(android.speech.RecognizerIntent.EXTRA_LANGUAGE_MODEL,
android.speech.RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
}
/**
* Implements OnClickListener.
*/
public void onVoiceClick(View v) {
/*if (v == mVoiceButton) {
startVoiceSearch();
} else {
mLauncher.onSearchRequested();
}*/
}
public void onClick(View v) {//sxyang modified.
mSearchText.setText("");
mSearchResult.setVisibility(View.INVISIBLE);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
/**
Log.w(TAG, "view="+view+"position="+position+"id="+id);
Map map = (Map)mAdapter.getItem(position);
Log.w(TAG, "onItemClick title="+map.get("title")+" intent="+map.get("intent"));
Intent intent = (Intent) map.get("intent");
getContext().startActivity(intent);
*/
}
private void startVoiceSearch() {
try {
getContext().startActivity(mVoiceSearchIntent);
} catch (ActivityNotFoundException ex) {
// Should not happen, since we check the availability of
// voice search before showing the button. But just in case...
Log.w(TAG, "Could not find voice search activity");
}
}
/**
* Sets the query text. The query field is not editable, instead we forward
* the key events to the launcher, which keeps track of the text,
* calls setQuery() to show it, and gives it to the search dialog.
*/
public void setQuery(String query) {
mSearchText.setText(query, TextView.BufferType.NORMAL);
}
/**
* Morph the search gadget to the search dialog.
* See {@link Activity#startSearch()} for the arguments.
*/
public void startSearch(String initialQuery, boolean selectInitialQuery,
Bundle appSearchData, boolean globalSearch) {
mInitialQuery = initialQuery;
mSelectInitialQuery = selectInitialQuery;
mAppSearchData = appSearchData;
mGlobalSearch = globalSearch;
showSearchDialog();
if (isAtTop()) {
// showSearchDialog();
} else {
// Call up the keyboard before we actually call the search dialog so that it
// (hopefully) animates in at about the same time as the widget animation, and
// so that it becomes available as soon as possible. Only do this if a hard
// keyboard is not currently available.
if (getContext().getResources().getConfiguration().hardKeyboardHidden ==
Configuration.HARDKEYBOARDHIDDEN_YES) {
InputMethodManager inputManager = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
// inputManager.showSoftInputUnchecked(0, null);
}
// Start the animation, unless it has already started.
// if (getAnimation() != mMorphAnimation) {
// mMorphAnimation.setDuration(getAnimationDuration());
// startAnimation(mMorphAnimation);
// }
}
}
/**
* Shows the system search dialog immediately, without any animation.
*/
private void showSearchDialog() {
Log.d(TAG, "showSearchDialog getText="+mSearchText.getText());
/*mLauncher.showSearchDialog(
mInitialQuery, mSelectInitialQuery, mAppSearchData, mGlobalSearch);*/
}
/**
* Restore the search gadget to its normal position.
*
* @param animate Whether to animate the movement of the gadget.
*/
public void stopSearch(boolean animate) {
setQuery("");
// Only restore if we are not already restored.
if (getAnimation() == mMorphAnimation) {
if (animate && !isAtTop()) {
mUnmorphAnimation.setDuration(getAnimationDuration());
startAnimation(mUnmorphAnimation);
} else {
clearAnimation();
}
}
}
private boolean isAtTop() {
return getWidgetTop() == 0;
}
private int getAnimationDuration() {
return (int) (getWidgetTop() / ANIMATION_VELOCITY);
}
/**
* Modify clearAnimation() to invalidate the parent. This works around
* an issue where the region where the end of the animation placed the view
* was not redrawn after clearing the animation.
*/
@Override
public void clearAnimation() {
Animation animation = getAnimation();
if (animation != null) {
super.clearAnimation();
if (animation.hasEnded()
&& animation.getFillAfter()
&& animation.willChangeBounds()) {
((View) getParent()).invalidate();
} else {
invalidate();
}
}
}
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (!event.isSystem() &&
(keyCode != KeyEvent.KEYCODE_DPAD_UP) &&
(keyCode != KeyEvent.KEYCODE_DPAD_DOWN) &&
(keyCode != KeyEvent.KEYCODE_DPAD_LEFT) &&
(keyCode != KeyEvent.KEYCODE_DPAD_RIGHT) &&
(keyCode != KeyEvent.KEYCODE_DPAD_CENTER)) {
// Forward key events to Launcher, which will forward text
// to search dialog
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
return mLauncher.onKeyDown(keyCode, event);
case KeyEvent.ACTION_MULTIPLE:
return mLauncher.onKeyMultiple(keyCode, event.getRepeatCount(), event);
case KeyEvent.ACTION_UP:
return mLauncher.onKeyUp(keyCode, event);
}
}
return false;
}
/**
* Implements OnLongClickListener to pass long clicks on child views
* to the widget. This makes it possible to pick up the widget by long
* clicking on the text field or a button.
*/
public boolean onLongClick(View v) {
return performLongClick();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mSearchText = (EditText) findViewById(R.id.search_src_text);
/**Begin: add by liuzepeng **/
if(android.provider.Settings.System.getInt(mContext.getContentResolver(),android.provider.Settings.System.ISIPHONE,0) == 1) {
mSearchText.setHint(R.string.search_hint_iphone);
}
/**End: add by liuzepeng **/
mVoiceButton = (ImageButton) findViewById(R.id.search_voice_btn);//sxyang modified.
mClearButton = (ImageButton) findViewById(R.id.search_clear_btn);//sxyang modified.
mSearchText.setOnKeyListener(this);
//mSearchText.setOnClickListener(this);
mVoiceButton.setOnClickListener(this);
mClearButton.setOnClickListener(this);//modified by liuzepeng
mSearchText.setOnLongClickListener(this);
mVoiceButton.setOnLongClickListener(this);
mSearchResultList = (ListView)findViewById(R.id.SearchResultView);
mSearchResult = (LinearLayout)findViewById(R.id.search_result);
mSearchResult.setVisibility(View.GONE);
/**
mData = new ArrayList<Map<String, Object>>();
mAdapter = new SimpleAdapter(getContext(),
mData,
R.layout.searchitem,
new String[]{"icon","title"},
new int[]{R.id.searchappicon,R.id.searchapptitle}
);
*/
/**
mAdapter.setViewBinder(new ViewBinder(){
@Override
public boolean setViewValue(View view ,Object data,String textRepresentation){
if(view instanceof ImageView && data instanceof Drawable){
ImageView iv=(ImageView)view;
iv.setImageDrawable((Drawable)data);
return true;
}
return false;
}
});
*/
configureVoiceSearchButton();
configureClearSearchButton();
mSearchResultList.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
InputMethodManager inputMethodManager = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(mSearchResultList.getWindowToken(), 0);
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}
});
if(cachedNumbers == null)
cachedNumbers = new HashMap<Long, String>();
dataList = new ArrayList<Info>();
mAdapter = new LockScreenAdapter(getContext(), dataList);
mSearchResultList.setAdapter(mAdapter);
mSearchText.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s) {}
public void beforeTextChanged(CharSequence s, int start, int count,int after) {}
public void onTextChanged(CharSequence s, int start, int before,int count) {
dataList.clear();
if (s == null || s.toString().equals("")|| mSearchText.getText().toString().trim() == null) {
mSearchResult.setVisibility(View.INVISIBLE);
return;
}
if(mQueryHandler == null)
mQueryHandler = new SearchQueryHandler(mLauncher.getContentResolver());
String filter = s.toString().replace("'",".");
startQuery(mQueryHandler, filter);
}});
}
private static Uri sAllCanonical = Uri.parse("content://mms-sms/canonical-addresses");
private static final int QUERY_FILTERED_SMS_TOKEN = 1000;
private static final int QUERY_THREAD_ID_TOKEN = 1001;
private static final int QUERY_FILTERED_CONTACTS_TOKEN = 1002;
private static final int QUERY_FAVORITES_TOKEN = 1003;
private static final int QUERY_PANEL_TOKEN = 1004;
private static final int CONTACTS_ID_INDEX = 0;
private static final int CONTACTS_LOOKUP_KEY_INDEX = 1;
private static final int CONTACTS_DISPLAY_NAME_INDEX = 2;
private static final int THREAD_ID_INDEX = 0;
private static final int RECIPIENT_IDS_INDEX = 3;
private static final int SNIPPET_INDEX = 4;
private static final int TYPE_MMS = 100;
private static final int TYPE_CONTACTS = 101;
private static final int TYPE_FAVORITES = 102;
private static final int TYPE_PANEL = 103;
private static final int TYPE_WEB = 104;
private SearchQueryHandler mQueryHandler;
private Map<Long, String> cachedNumbers;
private String[] CONTACTS_FILTER_PROJECTION = new String[] {
Contacts._ID, // 0
Contacts.LOOKUP_KEY, // 1
Contacts.DISPLAY_NAME, // 2
};
/**
* the query order is:favorites->panel->mms->contacts. At last, add web search
* cancel all querying process and start a new
*/
public void startQuery(AsyncQueryHandler handler, String filter) {
handler.cancelOperation(QUERY_FAVORITES_TOKEN);
handler.cancelOperation(QUERY_PANEL_TOKEN);
handler.cancelOperation(QUERY_THREAD_ID_TOKEN);
handler.cancelOperation(QUERY_FILTERED_SMS_TOKEN);
handler.cancelOperation(QUERY_FILTERED_CONTACTS_TOKEN);
startQueryFavorites(mQueryHandler, QUERY_FAVORITES_TOKEN, " title like '%"+filter+"%'", null , filter);//query favorites
}
public void startQueryFavorites(AsyncQueryHandler handler, int token,String selection,String[] selectionArgs, String filter) {
//handler.cancelOperation(token);
handler.startQuery(token, filter, LauncherSettings.Favorites.CONTENT_URI,
null, selection, selectionArgs, null);
}
public void startQueryPanel(AsyncQueryHandler handler, int token,String selection,String[] selectionArgs, String filter) {
//handler.cancelOperation(token);
handler.startQuery(token, filter, LauncherSettings.Panel.CONTENT_URI, null, selection, selectionArgs, null);
}
public void startQueryThreadIdFromMms(AsyncQueryHandler handler, int token,String selection,String[] selectionArgs, String filter) {
//handler.cancelOperation(token);
handler.startQuery(token, filter, Threads.CONTENT_URI,
new String[]{Conversations.THREAD_ID}, selection, selectionArgs, Conversations.IPHONE_DEFAULT_SORT_ORDER);
}
public void startQueryFilteredContentFromMms(AsyncQueryHandler handler, int token,String selection,String[] selectionArgs, String filter) {
//handler.cancelOperation(token);
handler.startQuery(token, filter, sAllThreadsUri,
ALL_THREADS_PROJECTION, selection, selectionArgs, Conversations.IPHONE_DEFAULT_SORT_ORDER);
}
public void startQueryFromContacts(AsyncQueryHandler handler, int token, String[] projection, String selection,String[] selectionArgs, String filter) {
handler.cancelOperation(token);
handler.startQuery(token, filter, Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI, filter),
projection, selection, selectionArgs, "sort_key");
}
private final class SearchQueryHandler extends AsyncQueryHandler {
Drawable mmsIcon = null, contactsIcon = null;
public SearchQueryHandler(ContentResolver contentResolver) {
super(contentResolver);
if(mmsIcon == null)
mmsIcon = getAppIcon("com.android.mms");
if(contactsIcon == null)
contactsIcon = getAppIcon("com.android.contacts");
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
//if(cursor == null) return;
//dataList.clear();
switch (token) {
case QUERY_FILTERED_SMS_TOKEN:
List<ItemInfo> itemInfoList = new ArrayList<ItemInfo>();
while(cursor.moveToNext()) {
long threadId = cursor.getLong(THREAD_ID_INDEX);
String snippet = cursor.getString(SNIPPET_INDEX);
String recipientIds = cursor.getString(RECIPIENT_IDS_INDEX);
String numbers = getAddresses(recipientIds);
if(!TextUtils.isEmpty(snippet) && !TextUtils.isEmpty(numbers)) {
ItemInfo itemInfo = new ItemInfo();
String title = numbers;
Intent intent = new Intent();
intent.setData(ContentUris.withAppendedId(Threads.CONTENT_URI, threadId));
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.putExtra("from", numbers);
//intent.putExtra("inner", true);//deleted by sunjinbiao on 20120814 for bug[548]
if (title!= null ) {
mSearchResult.setVisibility(View.VISIBLE);
itemInfo.title = title;
itemInfo.intent = intent;
}
itemInfoList.add(itemInfo);
}
}
//System.out.println("itemInfoList.size()="+itemInfoList.size());
if(itemInfoList.size()>0) {
Info info = new Info();
info.type = TYPE_MMS;
info.data = itemInfoList;
synchronized (dataList) {
dataList.add(info);
}
}
mAdapter.notifyDataSetChanged();
String filter = (String)cookie;
if(isDigits(filter) && filter.length() > 3) {
startQueryFromContacts(mQueryHandler, QUERY_FILTERED_CONTACTS_TOKEN, CONTACTS_FILTER_PROJECTION, null, null, filter);//query contacts
} else if(!isDigits(filter)) {
startQueryFromContacts(mQueryHandler, QUERY_FILTERED_CONTACTS_TOKEN, CONTACTS_FILTER_PROJECTION, null, null, filter);//query contacts
}
break;
case QUERY_THREAD_ID_TOKEN:
String id = null;
while(cursor.moveToNext()) {
if (id == null)
id = " _id = " + cursor.getLong(0);
else
id += " or _id = " + cursor.getLong(0);
}
if (id == null)
id = " _id = -1";
startQueryFilteredContentFromMms(mQueryHandler, QUERY_FILTERED_SMS_TOKEN,id, null, (String)cookie);
break;
case QUERY_FILTERED_CONTACTS_TOKEN:
itemInfoList = new ArrayList<ItemInfo>();
if(cursor == null) break;
while(cursor.moveToNext()) {
long contactId = cursor.getLong(CONTACTS_ID_INDEX);
String lookupKey = cursor.getString(CONTACTS_LOOKUP_KEY_INDEX);
String name = cursor.getString(CONTACTS_DISPLAY_NAME_INDEX);
Uri lookupUri = Contacts.getLookupUri(contactId, lookupKey);
ItemInfo itemInfo = new ItemInfo();
String title = name;
Intent intent = intent = new Intent(Intent.ACTION_VIEW, lookupUri);
if (title!= null ) {
mSearchResult.setVisibility(View.VISIBLE);
itemInfo.title = title;
itemInfo.intent = intent;
itemInfoList.add(itemInfo);
}
}
if(itemInfoList.size()>0) {
Info info = new Info();
info.type = TYPE_CONTACTS;
info.data = itemInfoList;
synchronized (dataList) {
dataList.add(info);
}
}
addWebSearch((String)cookie);
break;
case QUERY_FAVORITES_TOKEN:
int titleIndex = cursor.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
int iconIndex = cursor.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
int intentIndex = cursor.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
Intent intent=null;
PackageManager manager = getContext().getPackageManager();
Drawable icon=null;
while (cursor.moveToNext()) {
itemInfoList = new ArrayList<ItemInfo>();
ItemInfo itemInfo = new ItemInfo();
final String title = cursor.getString(titleIndex);
final String intentDescription = cursor.getString(intentIndex);
if(intentDescription == null)
continue;
try {
intent = Intent.parseUri(intentDescription, 0);
} catch (java.net.URISyntaxException e) {
}
icon = getApplicationsIcons(manager, getContext(), intent);
if (title!= null ) {
mSearchResult.setVisibility(View.VISIBLE);
itemInfo.title = title;
itemInfo.intent = intent;
itemInfo.icon = icon;
itemInfoList.add(itemInfo);
}
if(itemInfoList.size()>0) {
Info info = new Info();
info.type = TYPE_FAVORITES;
info.data = itemInfoList;
synchronized (dataList) {
dataList.add(info);
mAdapter.notifyDataSetChanged();
}
}
}
mAdapter.notifyDataSetChanged();
startQueryPanel(mQueryHandler, QUERY_PANEL_TOKEN, " title like '%"+((String)cookie)+"%'", null , (String)cookie);//query panel
break;
case QUERY_PANEL_TOKEN:
titleIndex = cursor.getColumnIndexOrThrow(LauncherSettings.Panel.TITLE);
iconIndex = cursor.getColumnIndexOrThrow(LauncherSettings.Panel.ICON);
intentIndex = cursor.getColumnIndexOrThrow(LauncherSettings.Panel.INTENT);
intent=null;
manager = getContext().getPackageManager();
icon=null;
while (cursor.moveToNext()) {
itemInfoList = new ArrayList<ItemInfo>();
ItemInfo itemInfo = new ItemInfo();
final String title = cursor.getString(titleIndex);
final String intentDescription = cursor.getString(intentIndex);
if(intentDescription == null)
continue;
try {
intent = Intent.parseUri(intentDescription, 0);
} catch (java.net.URISyntaxException e) {
//intent = null;
}
icon = getApplicationsIcons(manager, getContext(), intent);
if (title!= null ) {
mSearchResult.setVisibility(View.VISIBLE);
itemInfo.title = title;
itemInfo.intent = intent;
itemInfo.icon = icon;
itemInfoList.add(itemInfo);
}
if(itemInfoList.size()>0) {
Info info = new Info();
info.type = TYPE_PANEL;
info.data = itemInfoList;
synchronized (dataList) {
dataList.add(info);
mAdapter.notifyDataSetChanged();
}
}
}
mAdapter.notifyDataSetChanged();
startQueryThreadIdFromMms(mQueryHandler, QUERY_THREAD_ID_TOKEN," body like '%"+((String)cookie)+"%'", null, ((String)cookie));//query mms
break;
default:
Log.e(TAG, "onQueryComplete called with unknown token " + token);
}
cursor.close();
}
@Override
protected void onDeleteComplete(int token, Object cookie, int result) {}
}
private Info mFootInfo = null;
private void addWebSearch(String filter) {
/**Begin: add by liuzepeng **/
String editText = mSearchText.getText().toString().trim();
//Log.v("liuzepeng","filter:"+filter+"/mSearchText.getText():"+mSearchText.getText());
if(!editText.equals(filter)) {
filter = editText;
if(filter.equals("")) {
mSearchResult.setVisibility(View.INVISIBLE);
return;
}
}
/**Begin: add by liuzepeng **/
List<ItemInfo> itemInfoList = new ArrayList<ItemInfo>();
ItemInfo itemInfo = new ItemInfo();
Drawable icon = getAppIcon("com.android.browser");
Uri uri = Uri.parse("http://m.baidu.com/s?ie=utf-8&word="+filter);
Resources re = getContext().getResources();
String title = re.getString(R.string.web_search);
Intent intent = new Intent(Intent.ACTION_VIEW,uri);
if (title!= null ) {
mSearchResult.setVisibility(View.VISIBLE);
itemInfo.title = title;
itemInfo.intent = intent;
itemInfo.icon = icon;
itemInfoList.add(itemInfo);
}
if(mFootInfo == null){
mFootInfo = new Info();
mFootInfo.type = TYPE_WEB;
}
mFootInfo.data = itemInfoList;
/**Begin: modified by liuzepeng **/
if(!dataList.contains(mFootInfo)) {
dataList.add(mFootInfo);
} else {
dataList.remove(mFootInfo);
dataList.add(mFootInfo);
}
/**Begin: modified by liuzepeng **/
mAdapter.notifyDataSetChanged();
}
private Drawable getAppIcon(String packageName) {
List<PackageInfo> packages = getContext().getPackageManager().getInstalledPackages(0);
Drawable appIcon = null;
for (int i = 0; i < packages.size(); i++) {
PackageInfo packageInfo = packages.get(i);
if(packageInfo.packageName.equals(packageName)) {
appIcon = packageInfo.applicationInfo.loadIcon(getContext().getPackageManager());
break;
}
}
return appIcon;
}
public String getAddresses(String spaceSepIds) {
String numbers = "";
synchronized (cachedNumbers) {
String[] ids = spaceSepIds.split(" ");
for (String id : ids) {
long longId;
try {
longId = Long.parseLong(id);
} catch (NumberFormatException ex) {
// skip this id
continue;
}
String number = cachedNumbers.get(longId);
if (number == null) {
getNumbers();
number = cachedNumbers.get(longId);
}
if (TextUtils.isEmpty(number)) {
Log.w(TAG, "RecipientId " + longId + " has empty number!");
} else {
numbers += number;
}
}
return numbers;
}
}
public void getNumbers() {
final ContentResolver contentResolver = mLauncher.getContentResolver();
Cursor c = contentResolver.query(sAllCanonical, null, null, null, null);
if (c == null) {
Log.w(TAG, "null Cursor in fill()");
return;
}
try {
synchronized (cachedNumbers) {
// Technically we don't have to clear this because the stupid
// canonical_addresses table is never GC'ed.
cachedNumbers.clear();
while (c.moveToNext()) {
// TODO: don't hardcode the column indices
long id = c.getLong(0);
String number = c.getString(1);
cachedNumbers.put(id, number);
}
}
} finally {
c.close();
}
}
private boolean isDigits(String str) {
if(str == null || "".equals(str))
return false;
int len = str.length();
for(int i=0;i<len;i++) {
char c = str.charAt(i);
if(!Character.isDigit(c))
return false;
}
return true;
}
private class Info {
public int type;
public List<ItemInfo> data;
public String toString() {
return "type="+type;
}
}
private class ItemInfo {
public Drawable icon;
public String title;
public Intent intent;
public String toString() {
return "title="+title;
}
}
class LockScreenAdapter extends BaseAdapter {
private Context context;
List<Info> data;
LayoutInflater inflater;
Drawable mmsIcon = null, contactsIcon = null;
public LockScreenAdapter(Context aContext,List<Info> aData) {
context = aContext;
inflater = LayoutInflater.from(context);
data = aData;
if(mmsIcon == null)
mmsIcon = getAppIcon("com.android.mms");
if(contactsIcon == null)
contactsIcon = getAppIcon("com.android.contacts");
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return data.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.item_launcher_search, null);
if((position+1)%2 == 0 ){
convertView.setBackgroundDrawable(getResources().getDrawable(R.drawable.result0));
}else{
convertView.setBackgroundDrawable(getResources().getDrawable(R.drawable.result1));
}
int wrapContent = LinearLayout.LayoutParams.WRAP_CONTENT;
int fillParent = LinearLayout.LayoutParams.FILL_PARENT;
LinearLayout.LayoutParams contentsllp = new LinearLayout.LayoutParams(fillParent, wrapContent);
LinearLayout contents = (LinearLayout) convertView.findViewById(R.id.contents);
ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
Info info = data.get(position);
int type = info.type;
int size = info.data.size();
for (int i = 0; i < size; i++) {
ItemInfo itemInfo = info.data.get(i);
contents.addView(createItemView(itemInfo), contentsllp);
if(type == TYPE_MMS)
icon.setBackgroundDrawable(mmsIcon);
else if(type == TYPE_CONTACTS)
icon.setBackgroundDrawable(contactsIcon);
else
icon.setBackgroundDrawable(itemInfo.icon);
if(size>1 && i!=size -1){
TextView hLine = new TextView(getContext());
LinearLayout.LayoutParams hLinellp = new LinearLayout.LayoutParams(fillParent, wrapContent);
hLinellp.height = 1;
hLine.setBackgroundColor(Color.argb(255, 157, 157, 160));
contents.addView(hLine, hLinellp);
TextView bLine = new TextView(getContext());
bLine.setBackgroundColor(Color.argb(255, 255, 255, 255));
contents.addView(bLine, hLinellp);
}
}
return convertView;
}
}
LinearLayout createItemView(final ItemInfo itemInfo) {
final Context cxt = getContext();
LinearLayout contentLayout = new LinearLayout(cxt);
TextView seperatorLine = new TextView(cxt);
TextView content = new TextView(cxt);
int wrapContent = LinearLayout.LayoutParams.WRAP_CONTENT;
int fillParent = LinearLayout.LayoutParams.FILL_PARENT;
LinearLayout.LayoutParams seperatorLinellp = new LinearLayout.LayoutParams(wrapContent, 45);
seperatorLinellp.rightMargin = 50;
seperatorLinellp.height = 70;
LinearLayout.LayoutParams contentllp = new LinearLayout.LayoutParams(fillParent, 45);
contentllp.gravity=Gravity.CENTER_VERTICAL;
contentllp.leftMargin = 5;
seperatorLine.setBackgroundResource(R.drawable.launcher_item_vertical_line);
content.setText(itemInfo.title);
content.setTextColor(Color.BLACK);
content.setGravity(Gravity.CENTER_VERTICAL);
contentLayout.setOrientation(LinearLayout.HORIZONTAL);
contentLayout.addView(seperatorLine, seperatorLinellp);
contentLayout.addView(content, contentllp);
contentLayout.setBackgroundResource(R.drawable.search_item_press);
contentLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
cxt.startActivity(itemInfo.intent);
}
});
return contentLayout;
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
/**
* If appropriate & available, configure voice search
*
* Note: Because the home screen search widget is always web search, we only check for
* getVoiceSearchLaunchWebSearch() modes. We don't support the alternate form of app-specific
* voice search.
*/
private void configureVoiceSearchButton() {
// Enable the voice search button if there is an activity that can handle it
PackageManager pm = getContext().getPackageManager();
ResolveInfo ri = pm.resolveActivity(mVoiceSearchIntent,
PackageManager.MATCH_DEFAULT_ONLY);
boolean voiceSearchVisible = ri != null;
// finally, set visible state of voice search button, as appropriate
mVoiceButton.setVisibility(voiceSearchVisible ? View.VISIBLE : View.GONE);
}
private void configureClearSearchButton() {
//sxyang modified.
mSearchText.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s) {}
public void beforeTextChanged(CharSequence s, int start, int count,int after) {}
public void onTextChanged(CharSequence s, int start, int before,int count) {
if (s == null || s.toString().equals("")) {
mClearButton.setVisibility(View.INVISIBLE);
} else {
mClearButton.setVisibility(View.VISIBLE);
}
}});
}
/**
* Sets the {@link Launcher} that this gadget will call on to display the search dialog.
*/
public void setLauncher(Launcher launcher) {
mLauncher = launcher;
}
/**
* Moves the view to the top left corner of its parent.
*/
private class ToParentOriginAnimation extends Animation {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dx = -getLeft() * interpolatedTime;
float dy = -getWidgetTop() * interpolatedTime;
t.getMatrix().setTranslate(dx, dy);
}
}
/**
* Moves the view from the top left corner of its parent.
*/
private class FromParentOriginAnimation extends Animation {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dx = -getLeft() * (1.0f - interpolatedTime);
float dy = -getWidgetTop() * (1.0f - interpolatedTime);
t.getMatrix().setTranslate(dx, dy);
}
}
/**
* The widget is centered vertically within it's 4x1 slot. This is
* accomplished by nesting the actual widget inside another view. For
* animation purposes, we care about the top of the actual widget rather
* than it's container. This method return the top of the actual widget.
*/
private int getWidgetTop() {
return getTop() + getChildAt(0).getTop() + mWidgetTopOffset;
}
/*
* //2011-01-12 add for draw alpha
*/
public boolean setAlpha(int alpha) {
if (mAlpha != alpha) {
mAlpha = alpha;
Drawable background = findViewById(R.id.search_plate).getBackground();
//Drawable background = findViewById(R.id.search_plate).getBackground();
if (background != null) {
background.setAlpha(alpha);
} else {
Log.d(TAG, "background null");
}
background = findViewById(R.id.search_src_text).getBackground();
if (background != null) {
if (background instanceof StateListDrawable) {
StateListDrawable stateDrawable = (StateListDrawable)background;
int stateCount = stateDrawable.getStateCount();
for (int i = 0; i < stateCount; i++) {
Drawable d = stateDrawable.getStateDrawable(i);
d.setAlpha(alpha);
}
} else {
background.setAlpha(alpha);
}
} else {
Log.d(TAG, "background null");
}
this.invalidate();
return true;
}
return false;
}
/**
* Morph the search gadget to the search dialog.
* See {@link Activity#startSearch()} for the arguments.
*/
public void showstartSearch() {
//mSearchText.setText("", TextView.BufferType.NORMAL);
//mSearchResult.setVisibility(View.GONE);
if(mSearchResult.getVisibility() != View.VISIBLE) {
mSearchText.requestFocus();
Log.d(TAG, "showstartSearch");
if (getContext().getResources().getConfiguration().hardKeyboardHidden ==
Configuration.HARDKEYBOARDHIDDEN_YES) {
InputMethodManager inputManager = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInputUnchecked(0, null);
}
}
}
private Drawable getApplicationsIcons(PackageManager manager,Context context, Intent intent){
Drawable icon=null;
final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0);
if(resolveInfo == null) return null;
final ActivityInfo activityInfo = resolveInfo.activityInfo;
Drawable customerIcon = Utilities.getCustomerIcon(context, intent);
if(customerIcon != null){
icon = Utilities.createIconThumbnail(customerIcon, context);
} else {
icon = Utilities.createIconThumbnail(activityInfo.loadIcon(manager), context);
}
Bitmap bitmap = Utilities.createMiddleIcon(icon,context);
BitmapDrawable bd = new BitmapDrawable(bitmap);
return bd;
}
}
<com.hskj.hometest.Search
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher2"
android:id="@+id/widget_search"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="top">
<LinearLayout
android:id="@+id/search_plate"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="14dip"
android:paddingRight="4dip"
android:paddingTop="5dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:background="@drawable/textfield_searchwidget" >
<EditText
android:id="@+id/search_src_text"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:textSize="15sp"
android:paddingLeft="16dip"
android:hint="@string/search_hint"
android:singleLine="true"
android:background="@android:color/transparent"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
android:textColor="@android:color/primary_text_light"
/>
<ImageButton
android:id="@+id/search_clear_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="0dip"
android:background="@drawable/iphone_clean_icon"
/>
<ImageButton
android:id="@+id/search_voice_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dip"
android:background="@*android:drawable/btn_search_dialog_voice"
android:src="@*android:drawable/ic_btn_speak_now"
/>
</LinearLayout>
<LinearLayout android:id="@+id/search_result"
android:layout_weight="1"
android:layout_height="0dip"
android:layout_width="fill_parent"
android:layout_marginTop="5dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="11dip"
android:background="@drawable/search_list_bg">
<ListView android:layout_width="fill_parent"
android:id="@+id/SearchResultView"
android:scrollbars="vertical"
android:listSelector="@android:color/transparent"
android:cacheColorHint="#00000000"
android:divider="#CCCCCC"
android:dividerHeight="1px"
android:layout_height="fill_parent"
android:fadingEdge="none" >
</ListView>
</LinearLayout>
</com.hskj.hometest.Search>
<?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="fill_parent"
android:orientation="horizontal">
<ImageView android:id="@+id/icon" android:layout_width="30dip"
android:layout_height="30dip"
android:layout_margin="5dip" />
<LinearLayout android:id="@+id/contents"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:layout_toRightOf="@id/icon">
</LinearLayout>
</RelativeLayout>
精彩图集
精彩文章