仿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>

(0)

相关推荐

  • 仿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_VELOCI

  • YII框架中搜索分页jQuery写法详解

    控制层 use frontend\models\StudUser; use yii\data\Pagination; use yii\db\Query; /** * 查询 * */ public function actionSearch() { //接值 $where=Yii::$app->request->get(); //实例化query $query=new Query(); $query->from('stud_user'); //判断 if(isset($where['sex

  • umi插件开发仿dumi项目实现页面布局详解

    目录 实现思路 使用默认项目提供的layout文件 自定义主题 准备工作 主题插件功能 modifyAppData 插件代码 生成layout路由对象 使用同步伪代码来描述上面流程 运行检查 实现思路 上一章我们已经完成/docs目录下文件自动生路由功能,本章我们将在此基础上,实现自动生成页面导航的功能. 使用默认模板提供的layout展示路由切换 使用自定义主题插件 使用默认项目提供的layout文件 在我们创建默认umi项目后,会在/src/layouts下生成一个布局文件: 同时在上一章节

  • Android在fragment中编写toobar的步骤详解

    第一步的话就是首先导入我们的依赖的包: compile 'com.android.support:appcompat-v7:23.3.0' 第二步的话就是准备我们的布局文件和我们的item 在这的话我是将我们的toobar单独的放在一个布局文件中的方便以后的调用以及将我们的主题改为 我们noactionbar,同时在我们的主文件中进行引用 修改为nopactionbar 引用 设置单独的xml文件 然后的话就是我们在我们的这个位置设置的是我们的啊就是toobar的单独的一个文件代码如下: <?x

  • python编程之requests在网络请求中添加cookies参数方法详解

    哎,好久没有学习爬虫了,现在想要重新拾起来.发现之前学习爬虫有些粗糙,竟然连requests中添加cookies都没有掌握,惭愧.废话不宜多,直接上内容. 我们平时使用requests获取网络内容很简单,几行代码搞定了,例如: import requests res=requests.get("https://cloud.flyme.cn/browser/index.jsp") print res.content 你没有看错,真的只有三行代码.但是简单归简单,问题还是不少的. 首先,这

  • Java中正则表达式的使用和详解(下)

    在上篇给大家介绍了Java中正则表达式的使用和详解(上),具体内容如下所示: 1.常用正则表达式 规则 正则表达式语法   一个或多个汉字 ^[\u0391-\uFFE5]+$  邮政编码 ^[1-9]\d{5}$ QQ号码 ^[1-9]\d{4,10}$  邮箱 ^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\.){1,3}[a-zA-z\-]{1,}$  用户名(字母开头 + 数字/字母/下划线) ^[A-Za-z][A-Za-z1-9_-]+$ 手

  • Oracle中instr和substr存储过程详解

    instr和substr存储过程,分析内部大对象的内容 instr函数 instr函数用于从指定的位置开始,从大型对象中查找第N个与模式匹配的字符串. 用于查找内部大对象中的字符串的instr函数语法如下: dbms_lob.instr( lob_loc in blob, pattern in raw, offset in integer := 1; nth in integer := 1) return integer; dbms_lob.instr( lob_loc in clob char

  • BootStrap中Table分页插件使用详解

    分页(Pagination),是一种无序列表,Bootstrap 像处理其他界面元素一样处理分页. bootstrap-table介绍 bootstrap-table 是一个轻量级的table插件,使用AJAX获取JSON格式的数据,其分页和数据填充很方便,支持国际化. 下载地址 https://github.com/wenzhixin/bootstrap-table/archive/1.11.0.zip 使用方式 引入css和js <!--css样式--> <link href=&qu

  • Python中的变量和作用域详解

    作用域介绍 python中的作用域分4种情况: L:local,局部作用域,即函数中定义的变量: E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的: G:globa,全局变量,就是模块级别定义的变量: B:built-in,系统固定模块里面的变量,比如int, bytearray等. 搜索变量的优先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB. x = int(2.9) # int bu

  • Android中XUtils3框架使用方法详解(一)

    xUtils简介 xUtils 包含了很多实用的android工具. xUtils 支持大文件上传,更全面的http请求协议支持(10种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响... xUitls 最低兼容android 2.2 (api level 8) 今天给大家带来XUtils3的基本介绍,本文章的案例都是基于XUtils3的API语法进行的演示.相信大家对这个框架也都了解过, 下面简单介绍下XUtils3的一些基本知识. XUtils3一共有4大功能:注解模块,网络

随机推荐