Android組件DrawerLayout仿網(wǎng)易新聞v4.4側(cè)滑菜單
概述
今天這篇博客將記錄一些關(guān)于DrawerLayout的基本用法,我想關(guān)于DrawerLayout的用法也許有不少不夠了解,這也是比較正常的事情,因?yàn)镈rawerLayout作為Android組件是Google后來在android中添加的,在android.support.v4包下。那么,DrawerLayout是一個(gè)怎么的組件呢?我們知道,當(dāng)我們使用Android上各類App的時(shí)候,是不是注意過App主頁上通常有一個(gè)“側(cè)滑菜單”?關(guān)于側(cè)滑菜單的實(shí)現(xiàn),我在前面博客里有一些介紹,想多些了解的朋友請(qǐng)移步:
Android自定義控件——側(cè)滑菜單
Android自定義控件——開源組件SlidingMenu的項(xiàng)目集成
這里用“網(wǎng)易新聞”客戶端v4.4的截圖來說明一下,這個(gè)DrawerLayout抽屜式布局是什么樣子的。
好,大家已經(jīng)看到了,網(wǎng)易新聞客戶端效果很明顯,當(dāng)我們手指在屏幕左側(cè)向右滑動(dòng)時(shí)候,就會(huì)有一個(gè)抽屜式的菜單從左邊彈出,并且是“懸浮”在主界面之上的,合理的利用了設(shè)備上有限的空間,同樣手指在屏幕右側(cè)向左滑動(dòng)也會(huì)出現(xiàn)一個(gè)向左彈出的抽屜式菜單,用戶體驗(yàn)效果還是不錯(cuò)的,在DrawerLayout出現(xiàn)之前,我們需要做側(cè)滑菜單時(shí),不得不自己實(shí)現(xiàn)一個(gè)或者使用Github上的開源的項(xiàng)目SlidingMenu,也許是Google也看到了SlidingMenu的強(qiáng)大之處,于是在Android的后期版本中添加了DrawerLayout來實(shí)現(xiàn)SlidingMenu同樣功能的組件,而且為了兼容早期版本,將其添加在android,support.v4包下。
關(guān)于DrawerLayout的Training:http://developer.android.com/training/implementing-navigation/nav-drawer.html
關(guān)于DrawerLayout的API:http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html
另外,我已經(jīng)翻譯過了Google的Training課程,地址是:http://www.dbjr.com.cn/article/102142.htm
效果預(yù)覽
創(chuàng)建抽屜布局
下面這個(gè)抽屜布局引用的是android.support.v4.DrawerLayout,類似于LineaLayout、RelativeLayout等布局一樣定義,在DrawerLayout內(nèi)部再定義3個(gè)布局,分別是管理主界面的FrameLayout,此布局用來展示界面切換的Fragment,下面是ListView,用來展示菜單列表,最后是一個(gè)RelativeLayout,用來展示右邊的布局,布局代碼如下:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent" /> <ListView android:id="@+id/left_drawer" android:layout_width="200dp" android:layout_height="match_parent" android:layout_gravity="start" android:background="#111" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" /> <RelativeLayout android:id="@+id/right_drawer" android:layout_width="220dp" android:layout_height="match_parent" android:layout_gravity="end" android:background="#111" android:gravity="center_horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="這是右邊欄" android:textColor="@android:color/white" android:textSize="24sp" /> </RelativeLayout> </android.support.v4.widget.DrawerLayout>
這個(gè)布局文件示范了一些重要的布局特征.
- 主要內(nèi)容的視圖(FrameLayout)必須是DrawLayout的第一個(gè)子元素, 因?yàn)閷?dǎo)航抽屜是在主要內(nèi)容視圖的上面.
- 主要內(nèi)容視圖設(shè)置為匹配父視圖的寬度和高度, 因?yàn)樗砹苏麄€(gè)界面導(dǎo)航抽屜是隱藏的.
- 抽屜視圖(ListView)必須指定其水平重力與android:layout_gravity屬性。支持從右到左(RTL)語言,指定值與 "start" 代替 "left"(所以抽屜里出現(xiàn)在布局的右側(cè)當(dāng)布局是RTL時(shí)).這里將ListView設(shè)置為左邊欄菜單,所以android:layout_gravity屬性設(shè)置為“start”,將RelativeLayout設(shè)置為右邊欄,設(shè)置android:layout_gravity屬性為“end”.
- 抽屜視圖指定其寬度用dp單位和高度匹配父視圖。抽屜里的寬度不能超過320 dp, 所以用戶總是可以看到主要內(nèi)容視圖的一部分。
初始化抽屜列表
正如上述所講,因?yàn)镈rawerLayout里包含一個(gè)ListView作為左邊欄側(cè)滑菜單,所以我們需要首先初始化這個(gè)抽屜列表,并且為這個(gè)列表適配上數(shù)據(jù),數(shù)據(jù)適配器使用的是最簡(jiǎn)單的ArrayAdapter,模擬數(shù)據(jù)被簡(jiǎn)單的定義在res/values/strings.xml里,如下:
<string-array name="menu_array"> <item>Menu 1</item> <item>Menu 2</item> <item>Menu 3</item> <item>Menu 4</item> </string-array>
在Java代碼中,首先創(chuàng)建一個(gè)MainActivity繼承了android.support.v4.app.FragmentActivity,因?yàn)楹罄m(xù)中需要進(jìn)行Fragment之間的切換。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ...... // 初始化菜單列表 mMenuTitles = getResources().getStringArray(R.array.menu_array); mMenuListView.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mMenuTitles)); mMenuListView.setOnItemClickListener(new DrawerItemClickListener()); ...... }
處理導(dǎo)航點(diǎn)擊事件
當(dāng)用戶選擇了抽屜列表里面的一個(gè)Item時(shí), 系統(tǒng)調(diào)用onItemClickListener上的onItemClick(), 給setOnItemClickListener()你在onItemClick()方法里面做什么,在下面的例子中, 選擇每一個(gè)Item都會(huì)在主要內(nèi)容的布局中插入一個(gè)不同的Fragment.并且將導(dǎo)航列表的內(nèi)容傳遞給Fragment中顯示出來,下面是部分代碼:
/** * ListView上的Item點(diǎn)擊事件 * */ private class DrawerItemClickListener implements ListView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectItem(position); } } /** * 切換主視圖區(qū)域的Fragment * * @param position */ private void selectItem(int position) { // TODO Auto-generated method stub Fragment fragment = new ContentFragment(); Bundle args = new Bundle(); switch (position) { case 0: args.putString("key", mMenuTitles[position]); break; case 1: args.putString("key", mMenuTitles[position]); break; case 2: args.putString("key", mMenuTitles[position]); break; case 3: args.putString("key", mMenuTitles[position]); break; default: break; } fragment.setArguments(args); // FragmentActivity將點(diǎn)擊的菜單列表標(biāo)題傳遞給Fragment FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit(); // 更新選擇后的item和title,然后關(guān)閉菜單 mMenuListView.setItemChecked(position, true); setTitle(mMenuTitles[position]); mDrawerLayout.closeDrawer(mMenuListView); }
開源material-menu的集成
細(xì)心的朋友也許會(huì)發(fā)現(xiàn)“網(wǎng)易新聞”v4.4客戶端主頁左上角上有個(gè)菜單“動(dòng)態(tài)”的菜單按鈕,顯示流程是這樣的,當(dāng)菜單沒有打開時(shí),顯示“三”這樣的三條橫線,當(dāng)菜單打開(無論左右菜單)時(shí),會(huì)顯示“<-”這樣的按鈕,不停的變化,這樣的效果是不是有點(diǎn)絢麗???!了解過Android5.0的朋友,應(yīng)該會(huì)知道這種效果是使用了Android5.0新推出的Material Design設(shè)計(jì)語言做出來的效果,那么該怎么模仿這個(gè)效果呢?不好意思,由于偷懶,我已經(jīng)在牛牛的Github中找到了這樣的效果——material-menu組件,該組件模擬出了Android5.0下的Material Design效果,注意的是該組件中使用了JackWharton的NineOldAndroids動(dòng)畫效果。
material-menu主頁:https://github.com/balysv/material-menu
NineOldAndroids主頁:https://github.com/JakeWharton/NineOldAndroids
關(guān)于material-menu的使用可以參考其主頁上的Demo和說明,集成時(shí)需要下載NineOldAndroids導(dǎo)出jar集成到項(xiàng)目中。下面是我使用的部分代碼:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ...... // 設(shè)置抽屜打開時(shí),主要內(nèi)容區(qū)被自定義陰影覆蓋 mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); // 設(shè)置ActionBar可見,并且切換菜單和內(nèi)容視圖 getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeButtonEnabled(true); mMaterialMenuIcon = new MaterialMenuIcon(this, Color.WHITE, Stroke.THIN); mDrawerLayout.setDrawerListener(new DrawerLayout.SimpleDrawerListener() { @Override public void onDrawerSlide(View drawerView, float slideOffset) { showView = drawerView; if (drawerView == mMenuListView) { mMaterialMenuIcon.setTransformationOffset(MaterialMenuDrawable.AnimationState.BURGER_ARROW, isDirection_left ? 2 - slideOffset : slideOffset); } else if (drawerView == right_drawer) { mMaterialMenuIcon.setTransformationOffset(MaterialMenuDrawable.AnimationState.BURGER_ARROW, isDirection_right ? 2 - slideOffset : slideOffset); } } @Override public void onDrawerOpened(android.view.View drawerView) { if (drawerView == mMenuListView) { isDirection_left = true; } else if (drawerView == right_drawer) { isDirection_right = true; } } @Override public void onDrawerClosed(android.view.View drawerView) { if (drawerView == mMenuListView) { isDirection_left = false; } else if (drawerView == right_drawer) { isDirection_right = false; showView = mMenuListView; } } }); ...... }
此外,還需要關(guān)聯(lián)一下meterial-menu的狀態(tài),需要覆蓋Activity下的onPostCreate和onSaveInstanceState方法:
/** * 根據(jù)onPostCreate回調(diào)的狀態(tài),還原對(duì)應(yīng)的icon state */ @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mMaterialMenuIcon.syncState(savedInstanceState); } /** * 根據(jù)onSaveInstanceState回調(diào)的狀態(tài),保存當(dāng)前icon state */ @Override protected void onSaveInstanceState(Bundle outState) { mMaterialMenuIcon.onSaveInstanceState(outState); super.onSaveInstanceState(outState); }
添加ActionBar上的菜單按鈕
為了盡量模擬出“網(wǎng)易新聞”v4.4客戶端主頁,我也在標(biāo)題欄右上角添加一個(gè)小圖標(biāo),為了能在點(diǎn)擊這個(gè)小圖標(biāo)的時(shí)候彈出右邊欄菜單,實(shí)現(xiàn)方式很簡(jiǎn)單,關(guān)于ActionBar上添加導(dǎo)航的知識(shí)可以在csdn上搜到一些解釋或者上Android開發(fā)者官網(wǎng)查看源文檔,我這里首先簡(jiǎn)單的在res/menu下main.xml中這樣定義一個(gè):
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_personal" android:icon="@drawable/action_personal" android:orderInCategory="100" android:showAsAction="always" android:title="@string/action_personal"/> </menu>
完成定義操作后,需要加載菜單布局:
/** * 加載菜單 */ @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; }
標(biāo)題欄導(dǎo)航點(diǎn)擊事件處理
/** * 點(diǎn)擊ActionBar上菜單 */ @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case android.R.id.home: if (showView == mMenuListView) { if (!isDirection_left) { // 左邊欄菜單關(guān)閉時(shí),打開 mDrawerLayout.openDrawer(mMenuListView); } else {// 左邊欄菜單打開時(shí),關(guān)閉 mDrawerLayout.closeDrawer(mMenuListView); } } else if (showView == right_drawer) { if (!isDirection_right) {// 右邊欄關(guān)閉時(shí),打開 mDrawerLayout.openDrawer(right_drawer); } else {// 右邊欄打開時(shí),關(guān)閉 mDrawerLayout.closeDrawer(right_drawer); } } break; case R.id.action_personal: if (!isDirection_right) {// 右邊欄關(guān)閉時(shí),打開 if (showView == mMenuListView) { mDrawerLayout.closeDrawer(mMenuListView); } mDrawerLayout.openDrawer(right_drawer); } else {// 右邊欄打開時(shí),關(guān)閉 mDrawerLayout.closeDrawer(right_drawer); } break; default: break; } return super.onOptionsItemSelected(item); }
這段的邏輯有點(diǎn)繞,事實(shí)上我做的是這樣的,需要保證主界面上只能最多顯示一個(gè)菜單布局,當(dāng)左邊的菜單布局展示時(shí),此時(shí)打開右邊菜單布局時(shí),需要隱藏左邊菜單布局;同樣,如果右邊的菜單布局已經(jīng)在展示的時(shí)候,這時(shí)需要打開左邊菜單布局,必須首先隱藏掉右邊的菜單布局。為了判斷當(dāng)前即將顯示或者關(guān)閉的是哪個(gè)布局,我在全局變量中定義了showView用來標(biāo)記當(dāng)前即將顯示或者關(guān)閉的視圖,如果showView==mMenuListView,說明左邊菜單布局是即將被顯示或隱藏的,這時(shí)進(jìn)一步判斷菜單是視圖mMenuListView的是否已經(jīng)顯示的標(biāo)記isDirection_left,來打開或者關(guān)閉左邊視圖菜單。
同樣的道理,如果當(dāng)前即將顯示或者隱藏的是右邊導(dǎo)航菜單的話,我們需要進(jìn)一步判斷右邊導(dǎo)航是否已經(jīng)顯示,從而進(jìn)行相關(guān)打開或隱藏的決定。
這里的邏輯似乎解釋的有點(diǎn)亂,而且代碼是分片段貼出來的,不利于理解,需要進(jìn)一步理解的話,不妨繼續(xù)看下面的部分,我已經(jīng)貼出了所以的Java代碼,注釋也很詳盡,可以方便理解,實(shí)在不行,還可以點(diǎn)擊博客下方的下載鏈接,直接下載源碼運(yùn)行一下。
全部源碼
public class MainActivity extends FragmentActivity { /** DrawerLayout */ private DrawerLayout mDrawerLayout; /** 左邊欄菜單 */ private ListView mMenuListView; /** 右邊欄 */ private RelativeLayout right_drawer; /** 菜單列表 */ private String[] mMenuTitles; /** Material Design風(fēng)格 */ private MaterialMenuIcon mMaterialMenuIcon; /** 菜單打開/關(guān)閉狀態(tài) */ private boolean isDirection_left = false; /** 右邊欄打開/關(guān)閉狀態(tài) */ private boolean isDirection_right = false; private View showView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mMenuListView = (ListView) findViewById(R.id.left_drawer); right_drawer = (RelativeLayout) findViewById(R.id.right_drawer); this.showView = mMenuListView; // 初始化菜單列表 mMenuTitles = getResources().getStringArray(R.array.menu_array); mMenuListView.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mMenuTitles)); mMenuListView.setOnItemClickListener(new DrawerItemClickListener()); // 設(shè)置抽屜打開時(shí),主要內(nèi)容區(qū)被自定義陰影覆蓋 mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); // 設(shè)置ActionBar可見,并且切換菜單和內(nèi)容視圖 getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeButtonEnabled(true); mMaterialMenuIcon = new MaterialMenuIcon(this, Color.WHITE, Stroke.THIN); mDrawerLayout.setDrawerListener(new DrawerLayoutStateListener()); if (savedInstanceState == null) { selectItem(0); } } /** * ListView上的Item點(diǎn)擊事件 * */ private class DrawerItemClickListener implements ListView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectItem(position); } } /** * DrawerLayout狀態(tài)變化監(jiān)聽 */ private class DrawerLayoutStateListener extends DrawerLayout.SimpleDrawerListener { /** * 當(dāng)導(dǎo)航菜單滑動(dòng)的時(shí)候被執(zhí)行 */ @Override public void onDrawerSlide(View drawerView, float slideOffset) { showView = drawerView; if (drawerView == mMenuListView) {// 根據(jù)isDirection_left決定執(zhí)行動(dòng)畫 mMaterialMenuIcon.setTransformationOffset( MaterialMenuDrawable.AnimationState.BURGER_ARROW, isDirection_left ? 2 - slideOffset : slideOffset); } else if (drawerView == right_drawer) {// 根據(jù)isDirection_right決定執(zhí)行動(dòng)畫 mMaterialMenuIcon.setTransformationOffset( MaterialMenuDrawable.AnimationState.BURGER_ARROW, isDirection_right ? 2 - slideOffset : slideOffset); } } /** * 當(dāng)導(dǎo)航菜單打開時(shí)執(zhí)行 */ @Override public void onDrawerOpened(android.view.View drawerView) { if (drawerView == mMenuListView) { isDirection_left = true; } else if (drawerView == right_drawer) { isDirection_right = true; } } /** * 當(dāng)導(dǎo)航菜單關(guān)閉時(shí)執(zhí)行 */ @Override public void onDrawerClosed(android.view.View drawerView) { if (drawerView == mMenuListView) { isDirection_left = false; } else if (drawerView == right_drawer) { isDirection_right = false; showView = mMenuListView; } } } /** * 切換主視圖區(qū)域的Fragment * * @param position */ private void selectItem(int position) { Fragment fragment = new ContentFragment(); Bundle args = new Bundle(); switch (position) { case 0: args.putString("key", mMenuTitles[position]); break; case 1: args.putString("key", mMenuTitles[position]); break; case 2: args.putString("key", mMenuTitles[position]); break; case 3: args.putString("key", mMenuTitles[position]); break; default: break; } fragment.setArguments(args); // FragmentActivity將點(diǎn)擊的菜單列表標(biāo)題傳遞給Fragment FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, fragment).commit(); // 更新選擇后的item和title,然后關(guān)閉菜單 mMenuListView.setItemChecked(position, true); setTitle(mMenuTitles[position]); mDrawerLayout.closeDrawer(mMenuListView); } /** * 點(diǎn)擊ActionBar上菜單 */ @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case android.R.id.home: if (showView == mMenuListView) { if (!isDirection_left) { // 左邊欄菜單關(guān)閉時(shí),打開 mDrawerLayout.openDrawer(mMenuListView); } else {// 左邊欄菜單打開時(shí),關(guān)閉 mDrawerLayout.closeDrawer(mMenuListView); } } else if (showView == right_drawer) { if (!isDirection_right) {// 右邊欄關(guān)閉時(shí),打開 mDrawerLayout.openDrawer(right_drawer); } else {// 右邊欄打開時(shí),關(guān)閉 mDrawerLayout.closeDrawer(right_drawer); } } break; case R.id.action_personal: if (!isDirection_right) {// 右邊欄關(guān)閉時(shí),打開 if (showView == mMenuListView) { mDrawerLayout.closeDrawer(mMenuListView); } mDrawerLayout.openDrawer(right_drawer); } else {// 右邊欄打開時(shí),關(guān)閉 mDrawerLayout.closeDrawer(right_drawer); } break; default: break; } return super.onOptionsItemSelected(item); } /** * 根據(jù)onPostCreate回調(diào)的狀態(tài),還原對(duì)應(yīng)的icon state */ @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mMaterialMenuIcon.syncState(savedInstanceState); } /** * 根據(jù)onSaveInstanceState回調(diào)的狀態(tài),保存當(dāng)前icon state */ @Override protected void onSaveInstanceState(Bundle outState) { mMaterialMenuIcon.onSaveInstanceState(outState); super.onSaveInstanceState(outState); } /** * 加載菜單 */ @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
源碼請(qǐng)?jiān)谶@里下載:http://xiazai.jb51.net/201701/yuanma/AndroidDrawerLayout(jb51.net).rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android使用DrawerLayout實(shí)現(xiàn)仿QQ雙向側(cè)滑菜單
- Android原生側(cè)滑控件DrawerLayout使用方法詳解
- Android官方的側(cè)滑控件DrawerLayout的示例代碼
- Android中DrawerLayout實(shí)現(xiàn)側(cè)滑菜單效果
- Android DrawerLayout帶有側(cè)滑功能的布局類(1)
- Android側(cè)滑菜單控件DrawerLayout使用詳解
- Android之側(cè)滑菜單DrawerLayout的使用介紹
- android側(cè)滑菜單控件DrawerLayout使用方法詳解
- Android使用DrawerLayout實(shí)現(xiàn)側(cè)滑菜單效果
- Android布局控件DrawerLayout實(shí)現(xiàn)完美側(cè)滑效果
相關(guān)文章
Android開發(fā)筆記之:返回鍵的復(fù)寫onBackPressed()介紹
本篇文章是對(duì)Android中返回鍵的復(fù)寫onBackPressed()進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Android 照片選擇區(qū)域功能實(shí)現(xiàn)示例
這篇文章主要介紹了Android 照片選擇區(qū)域功能實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Android金額輸入框只允許輸入小數(shù)點(diǎn)后兩位效果
實(shí)現(xiàn)android 金額輸入框輸入小數(shù)點(diǎn)后兩位的效果也不是很復(fù)雜,只需要設(shè)置輸入框輸入的字符類型、設(shè)置InputFilter、設(shè)置輸入變化監(jiān)聽即可。這篇文章主要介紹了Android金額輸入框只允許輸入小數(shù)點(diǎn)后兩位 ,需要的朋友可以參考下2017-05-05android Handler詳細(xì)使用方法實(shí)例
本文主要介紹Android中Handler的簡(jiǎn)單使用方法,Handler跟多線程,消息隊(duì)列聯(lián)系很緊密,在平常的實(shí)際程序開發(fā)中比較常見。本文分為4個(gè)簡(jiǎn)單的例子來學(xué)校handler2013-11-11android 引導(dǎo)界面的實(shí)現(xiàn)方法
現(xiàn)在越來越多程序都有引導(dǎo)頁面了。網(wǎng)上資料不全?,F(xiàn)在自己實(shí)現(xiàn)下。2013-06-06Android8.1 通過黑名單屏蔽系統(tǒng)短信和來電功能
最近小編接到一個(gè)新的需求,需要將8.1 設(shè)備的來電功能和短信功能都屏蔽掉,特殊產(chǎn)品就是特殊定制。接下來通過本文給大家介紹Android8.1 通過黑名單屏蔽系統(tǒng)短信和來電功能,需要的朋友參考下吧2019-05-05Android使用系統(tǒng)自帶的相機(jī)實(shí)現(xiàn)一鍵拍照功能
這篇文章主要介紹了Android使用系統(tǒng)自帶的相機(jī)實(shí)現(xiàn)一鍵拍照功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-01-01