編輯:關於Android編程
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { public boolean onCreateActionMode(ActionMode mode, Menu menu) { MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); return true; } //該方法用於創建Menu視圖 public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.menu_share: shareCurrentItem(); mode.finish(); return true; default: return false; } } //該方法用於對用戶的操作做出相應的反饋 public void onDestroyActionMode(ActionMode mode) { mActionMode = null; } //及時清除mActionMode引用,一者為了垃圾回收,二者為了後面再次進入上下文操作模式考慮 }
private ActionMode mActionMode; someView.setOnLongClickListener(new View.OnLongClickListener() { //someView是一個普通的View控件 public boolean onLongClick(View view) { if (mActionMode == null) { mActionMode = getActivity().startActionMode(mActionModeCallback)}; //根據情況如果消耗事件則返回true,沒有消耗事件則返回false。 view.setSelected(true); .............. return true; } });
public ActionMode startActionMode(ActionMode.Callback callback) { return mWindow.getDecorView().startActionMode(callback); }其中mWindow = new PhoneWindow(this);因此我們往下看PhoneWindow的startActionMode方法。 @PhoneWindow.class
public ActionMode startActionMode(ActionMode.Callback callback) { if (mActionMode != null) { mActionMode.finish(); } final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); ActionMode mode = null; ........... if (mode != null) { mActionMode = mode; } else { if (mActionModeView == null) {//創建ActionModeView if (isFloating()) { mActionModeView = new ActionBarContextView(mContext);//note1 mActionModePopup = new PopupWindow(mContext, null, com.android.internal.R.attr.actionModePopupWindowStyle); mActionModePopup.setWindowLayoutType( WindowManager.LayoutParams.TYPE_APPLICATION); mActionModePopup.setContentView(mActionModeView); //mActionModeView這裡是准備被顯示的View mActionModePopup.setWidth(MATCH_PARENT); TypedValue heightValue = new TypedValue(); mContext.getTheme().resolveAttribute( com.android.internal.R.attr.actionBarSize, heightValue, true); final int height = TypedValue.complexToDimensionPixelSize(heightValue.data, mContext.getResources().getDisplayMetrics()); mActionModeView.setContentHeight(height); mActionModePopup.setHeight(WRAP_CONTENT); mShowActionModePopup = new Runnable() { public void run() { mActionModePopup.showAtLocation( //note2 mActionModeView.getApplicationWindowToken(), Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0); } }; } else { ViewStub stub = (ViewStub) findViewById( com.android.internal.R.id.action_mode_bar_stub); if (stub != null) { mActionModeView = (ActionBarContextView) stub.inflate(); } } } if (mActionModeView != null) { //顯示ActionModeView mActionModeView.killMode(); mode = new StandaloneActionMode(getContext(), mActionModeView, wrappedCallback, mActionModePopup == null); if (callback.onCreateActionMode(mode, mode.getMenu())) {//創建菜單到ActionMode中 mode.invalidate(); mActionModeView.initForMode(mode);//note3 mActionModeView.setVisibility(View.VISIBLE); mActionMode = mode; if (mActionModePopup != null) { post(mShowActionModePopup); //交給Handler去執行前面的Runnable異步方法 } mActionModeView.sendAccessibilityEvent( AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } else { mActionMode = null; } } } .... return mActionMode; }------------------------------------------------------------- note1: ActionBarContextView()@ActionBarContextView.class ActionBarContextView(mContext)-->最終調用構造器為:public ActionBarContextView( Context context, null,com.android.internal.R.attr.actionModeStyle, 0) 構造器內部會調用final TypedArray a = context.obtainStyledAttributes( null,R.styleable.ActionMode,com.android.internal.R.attr.actionModeStyle, 0);即從主題中定義的actionModeStyle樣式文件中和主題直接定義的屬性中獲取到如下屬性:
public void showAtLocation(IBinder token, int gravity, int x, int y) { ......... final WindowManager.LayoutParams p = createPopupLayoutParams(token); preparePopup(p); ..... invokePopup(p); }將視圖顯示到手機界面上。具體內容講完note3後就會詳細分析。 note3 @ActionBarContextView.class
public void initForMode(final ActionMode mode) { if (mClose == null) { LayoutInflater inflater = LayoutInflater.from(mContext); mClose = inflater.inflate(mCloseItemLayout, this, false); //看到這裡都想哭了,,,,,,,找了半天就是想搞明白那個返回鍵究竟在哪設置的!!!! //這裡終於找到了,mCloseItemLayout就是定義了返回鍵的布局文件,它的定義看note1,即ActionBarContextView的構造器。 addView(mClose); } else if (mClose.getParent() == null) { addView(mClose); } View closeButton = mClose.findViewById(R.id.action_mode_close_button); closeButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { mode.finish(); //點擊返回按鈕則銷毀當前ActionBarContextView視圖 } }); .... }------------------------------------------------------------- 最後我們可以對PopupWindow做一個總結:PopupWindow.setContentView(View v); 方法參數是PopupWindow將要具體顯示的內容,而PopupWindow的任務就是在屏幕中合適的位置將該View顯示出來。但是該方法並不會將View顯示出來,需要調用如下兩個方法才能最終顯示出來:showAtLocation(View parent, int gravity, int x, int y)、showAsDropDown(View anchor, int xoff, int yoff)。showAtLocation是在一個特定的位置中顯示視圖,而showAsDropDown則會首先選取指定視圖的左下方或者左上方顯示視圖。showAtLocation()和showAsDropDown()兩者底層顯示過程基本一致,先後調用preparePopup()和 invokePopup()方法,前者對即將顯示的視圖進行初始化操作,後者調用mWindowManager.addView(decorView, p);將視圖顯示出來。 PopupWindow的構造器中有如下的方法:final TypedArray a = context.obtainStyledAttributes( null, R.styleable.PopupWindow, com.android.internal.R.attr.popupWindowStyle,0);因此它從主題中定義的popupWindowStyle樣式文件中和主題直接定義的屬性中獲取到如下屬性:
try { Field field = popupMenu.getClass().getDeclaredField("mPopup"); field.setAccessible(true); MenuPopupHelper mHelper = (MenuPopupHelper) field.get(popupMenu); mHelper.setForceShowIcon(true); } catch (IllegalAccessException | NoSuchFieldException e) { e.printStackTrace(); }
private void showPopupMenu(View v){ PopupMenu popup = new PopupMenu(this, v); MenuInflater inflater = popup.getMenuInflater(); inflater.inflate(R.menu.popmenu, popup.getMenu()); try { Field field = popup.getClass().getDeclaredField("mPopup"); field.setAccessible(true); MenuPopupHelper mHelper = (MenuPopupHelper) field.get(popup); mHelper.setForceShowIcon(true); } catch (IllegalAccessException | NoSuchFieldException e) { e.printStackTrace(); } popup.setOnMenuItemClickListener(new OnPopupMenuItemClickListener(this)); popup.setGravity(Gravity.RIGHT); popup.show(); }補充4:主題設置(PopupMenu的字體背景等) 在xml文件中
注意:上面的ProfileTheme在manifest.xml文件中可以加給某個Activity如:
public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflater.inflate(ITEM_LAYOUT, parent, false); //note1 } MenuView.ItemView itemView = (MenuView.ItemView) convertView; if (mForceShowIcon) { ((ListMenuItemView) convertView).setForceShowIcon(true); //note2 } itemView.initialize(getItem(position), 0); //note3 return convertView; }1、static final int ITEM_LAYOUT = R.layout.abc_popup_menu_item_layout;該布局文件只有一個Title和SubTitle的布局信息。外面包裹的是一個android.support.v7.view.menu.ListMenuItemView類型(是一個繼承自LinearLayout的類) 2、設置ListMenuItemView的標志位 mPreserveIconSpacing = mForceShowIcon = true。mForceShowIcon域可以通過MenuPopupHelper的setForceShowIcon方法進行設置,默認是false。 3、調用android.support.v7.view.menu.ListMenuItemView的initialize方法對該行視圖進行初始化設置:設置title、icon等。最後返回當前的convertView對象。 MenuPopupHelper中的MenuAdapter的傳遞 android.support.v7.view.menu.MenuPopupHelper在創建android.support.v7.widget.ListPopupWindow對象的時候會將MenuAdapter傳過去。android.support.v7.widget.ListPopupWindow在創建android.support.v7.widget.ListPopupWindow.DropDownListView的時候也會將MenuAdapter傳過去。DropDownListView是一個繼承自ListView的控件,之後就是ListView和Adapter的情況了,該部分可以參考ListView知識。
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ListPopupWindow, R.attr.popupMenuStyle, 0);即從主題中定義的popupMenuStyle樣式文件中和主題直接定義的屬性中獲取到如下屬性:DropDownListView的構造器中有如下方法: final TypedArray a =context.obtainStyledAttributes( attrs, R.styleable.ListView, R.attr.dropDownListViewStyle, 0);即從主題中定義的dropDownListViewStyle樣式文件中和主題直接定義的屬性中獲取到如下屬性:
如何在ES文件浏覽器內使用網盤。是一款多功能的手機文件/程序/進程管理器,可以在手機、電腦、遠程和藍牙間浏覽管理文件,是一個功能強大的免費的本地和網絡文件管
本教程為大家分享了Android發布微博、添加表情等功能的具體代碼,供大家參考,具體內容如下發布一條新微博接口:http://open.weibo.com/wiki/2/
本文實例講述了Android改變手機屏幕朝向的方法。分享給大家供大家參考。具體如下:模擬當點擊按鈕時,使手機朝向發生改變。main.xml布局文件:<?xm
前言相信很多朋友在開發中都會遇到圖片上傳的情況,尤其是多圖上傳,最經典的莫過於微信的圖片選擇了。所有很多情況下會使用到多圖選擇,所以就有了這篇文章,今天抽點時間寫了個控件