Android仿今日頭條APP實(shí)現(xiàn)下拉導(dǎo)航選擇菜單效果
本文實(shí)例為大家分享了在Android中如何實(shí)現(xiàn)下拉導(dǎo)航選擇菜單效果的全過(guò)程,供大家參考,具體內(nèi)容如下
關(guān)于下拉導(dǎo)航選擇菜單效果在新聞客戶(hù)端中用的比較多,當(dāng)然也可以用在其他的項(xiàng)目中,這樣可以很方便的選擇更多的菜單。我們可以讓我們的應(yīng)用頂部有左右滑動(dòng)或進(jìn)行切換的導(dǎo)航菜單,也可以為了增強(qiáng)用戶(hù)體驗(yàn)在應(yīng)用中添加這樣的下拉導(dǎo)航選擇菜單效果。
關(guān)于它的實(shí)現(xiàn)原理,其實(shí)也是挺簡(jiǎn)單的,就是使用PopupWindow來(lái)進(jìn)行展現(xiàn),在顯示時(shí)控制其高度并配置以相應(yīng)的動(dòng)畫(huà)效果。在PopupWindow中我使用GridView來(lái)控制里面的菜單項(xiàng),每個(gè)菜單項(xiàng)對(duì)應(yīng)相應(yīng)的圖片和文字。當(dāng)然了,也有其他的實(shí)現(xiàn)方式。為了大家能夠清楚的理解,讓我們先看下效果圖,如下所示:
以上就是我實(shí)現(xiàn)的示例圖,大家已經(jīng)看到了,就是點(diǎn)擊應(yīng)用頂部中間的文字時(shí)展現(xiàn)出來(lái),在我們點(diǎn)擊其中一項(xiàng)菜單時(shí)隱藏并加載相應(yīng)菜單的內(nèi)容,同時(shí)該菜單處于選中狀態(tài)。好了,下面就讓我們開(kāi)始我們的實(shí)現(xiàn)過(guò)程,還是先看下程序結(jié)構(gòu)圖吧:
在程序結(jié)構(gòu)圖中,PulldownMenuView是對(duì)PopupWindow進(jìn)行的封裝類(lèi),PulldownMenuItem是菜單項(xiàng)類(lèi),這是兩個(gè)重要的類(lèi)。在我們點(diǎn)擊應(yīng)用頂部中間的文字時(shí),要進(jìn)行展現(xiàn),展現(xiàn)的同時(shí),要實(shí)現(xiàn)對(duì)菜單的初始化工作,首先是初始化數(shù)據(jù),其主要代碼如下:
/** * 初始化數(shù)據(jù),將數(shù)據(jù)加載到對(duì)應(yīng)的View中 */ private void initData(){ PulldownMenuItem item = new PulldownMenuItem(context); item.setMenuAlign(menuAlign); item.setMenuTextColor(menuTextColor); item.setMenuTextSize(menuTextSize); int txtLength = menuTexts.length; int imgLength = menuImageRes.length; if (txtLength != 0 && imgLength != 0){ for (int i = 0; i < imgLength; i++){ PulldownMenuItem menuItem = new PulldownMenuItem(context, item); if(!currentItem.equals(menuTexts[i])){ menuItem.setImageRes(menuImageRes[i]); menuItem.setMenuText(menuTexts[i]); }else{ menuItem.setMenuText(menuTexts[i]); menuItem.setMenuTextColor(Color.parseColor("#4FA7F9")); menuItem.setImageRes(ConstantCategoryMenu.newsImageResPress[i]); } menuMenuItems.add(menuItem); } } else{ if (txtLength != 0){ for (int i = 0; i < txtLength; i++){ PulldownMenuItem menuItem = new PulldownMenuItem(context, item); if(!currentItem.equals(menuTexts[i])){ menuItem.setMenuText(menuTexts[i]); }else{ menuItem.setMenuText(menuTexts[i]); menuItem.setMenuTextColor(Color.parseColor("#4FA7F9")); } menuMenuItems.add(menuItem); } }else if (imgLength != 0){ for (int i = 0; i < imgLength; i++){ PulldownMenuItem menuItem = new PulldownMenuItem(context, item); menuItem.setImageRes(menuImageRes[i]); menuMenuItems.add(menuItem); } } } }
currentItem代表當(dāng)前的選擇項(xiàng),在初始化數(shù)據(jù)過(guò)程中,需要檢測(cè)哪項(xiàng)菜單被選中了,如果某項(xiàng)菜單被選中,則在展開(kāi)時(shí)需要將該項(xiàng)菜單圖片和文字顏色設(shè)置成相應(yīng)狀態(tài),表示該項(xiàng)菜單被選中。在初始化過(guò)程中分為三種情況:第一種是菜單項(xiàng)既有圖片也有文字;第二種是菜單項(xiàng)只有文字;第三種是菜單項(xiàng)只有圖片;所以在上面代碼中需要進(jìn)行相應(yīng)判斷。上面是初始化菜單中的數(shù)據(jù),下面是初始化菜單中的內(nèi)容:
/** * 初始化菜單內(nèi)容 * @param context * @param columns 菜單的列數(shù) * @return */ private GridView getMenuGirdView(Context context, int columns){ if (menuMenuItems.isEmpty()){ // 初始化菜單數(shù)據(jù) initData(); } if (null != menuGridView){ return menuGridView; } GridView gridView = new GridView(context); gridView.setLayoutParams(new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); // 設(shè)置數(shù)據(jù)適配器 gridView.setAdapter(new PulldownMenuAdapter(menuMenuItems)); gridView.setVerticalSpacing(1); gridView.setNumColumns(columns); gridView.setGravity(Gravity.CENTER); gridView.setVerticalScrollBarEnabled(false); if (menuBackground != 0){ gridView.setBackgroundResource(menuBackground); } if (menuSelector != -1){ gridView.setSelector(menuSelector); } gridView.setHorizontalScrollBarEnabled(false); setMenuListener(gridView); return gridView; }
初始化菜單之后,就需要我們菜單中相應(yīng)的數(shù)據(jù),設(shè)置數(shù)據(jù)比較容易,只需要三個(gè)數(shù)組即可:第一個(gè)數(shù)組代表菜單項(xiàng)文字內(nèi)容;第二個(gè)數(shù)組代表菜單項(xiàng)圖片資源,第三個(gè)數(shù)組代表菜單項(xiàng)被選中的圖片資源。如下代碼:
/** * 新聞菜單項(xiàng)圖片資源 */ public final static int[] newsImageRes = { R.drawable.ic_menu_toutiao,R.drawable.ic_menu_gn, R.drawable.ic_menu_gj,R.drawable.ic_menu_sh, R.drawable.ic_menu_sport,R.drawable.ic_menu_nba, R.drawable.ic_menu_blog,R.drawable.ic_menu_book, R.drawable.ic_menu_yule,R.drawable.ic_menu_mil, R.drawable.ic_menu_cj,R.drawable.ic_menu_tech, R.drawable.ic_menu_mobile,R.drawable.ic_menu_women, R.drawable.ic_menu_car,R.drawable.ic_menu_house }; /** * 新聞菜單項(xiàng)選中圖片資源 */ public final static int[] newsImageResPress = { R.drawable.ic_menu_toutiao_press,R.drawable.ic_menu_gn_press, R.drawable.ic_menu_gj_press,R.drawable.ic_menu_sh_press, R.drawable.ic_menu_sport_press,R.drawable.ic_menu_nba_press, R.drawable.ic_menu_blog_press,R.drawable.ic_menu_book_press, R.drawable.ic_menu_yule_press,R.drawable.ic_menu_mil_press, R.drawable.ic_menu_cj_press,R.drawable.ic_menu_tech_press, R.drawable.ic_menu_mobile_press,R.drawable.ic_menu_women_press, R.drawable.ic_menu_car_press,R.drawable.ic_menu_house_press }; /** * 新聞菜單項(xiàng)文字 */ public final static String[] newsMenuTexts = { "今日頭條","國(guó)內(nèi)","國(guó)際","社會(huì)","體育","NBA","博客","讀書(shū)", "娛樂(lè)","軍事","財(cái)經(jīng)","科技","手機(jī)","女性","汽車(chē)","房產(chǎn)" };
菜單項(xiàng)使用GridView實(shí)現(xiàn),我們還需要設(shè)置每個(gè)菜單項(xiàng)的監(jiān)聽(tīng)事件,在選中一項(xiàng)菜單后或是點(diǎn)擊返回鍵或點(diǎn)擊菜單鍵時(shí)實(shí)現(xiàn)隱藏,代碼如下:
/** * 設(shè)置菜單項(xiàng)監(jiān)聽(tīng)事件 * @param gridView */ private void setMenuListener(GridView gridView){ if (null == gridView.getOnItemClickListener()){ gridView.setOnItemClickListener(new OnItemClickListener(){ @Override public void onItemClick( AdapterView<?> parent, View view, int position, long id){ if (null != menuItemListener){ menuItemListener.onMenuItemClick(parent, view, position); } hide(); } }); } // 按返回鍵或菜單鍵隱藏菜單 gridView.setOnKeyListener(new OnKeyListener(){ @Override public boolean onKey(View v, int keyCode, KeyEvent event){ if (event.getAction() == KeyEvent.ACTION_DOWN){ switch (keyCode){ case KeyEvent.KEYCODE_BACK: case KeyEvent.KEYCODE_MENU: hide(); break; } } return false; } }); }
在PulldownMenuView類(lèi)中的show()和hide()方法中,主要是實(shí)現(xiàn)菜單的顯示與隱藏。在show()方法中,要計(jì)算每行存放的菜單數(shù)、設(shè)置相應(yīng)的高度、菜單整體的背景、動(dòng)畫(huà)效果、菜單顯示的位置等效果。具體不再詳述。
我們?cè)陲@示下拉導(dǎo)航選擇菜單前還需要配置菜單相應(yīng)的參數(shù),比如顯示位置、背景圖片、高度等。這就是在MenuUtility類(lèi)中要實(shí)現(xiàn)的,代碼如下:
package com.navigation.utility; import com.navigation.acitvity.R; import com.navigation.control.PulldownMenuView; import android.content.Context; import android.view.View; /** * PulldownMenuView基本操作類(lèi) * @Description: PulldownMenuView基本操作類(lèi) * @File: PulldownMenuUtility.java * @Package com.navigation.utility * @Author Hanyonglu * @Date 2012-7-30 上午11:41:04 * @Version V1.0 */ public class MenuUtility { private Context context = null; // PulldownMenuView對(duì)象 private PulldownMenuView menu = null; // 圖片資源 private int[] imageRes = null; // 文字內(nèi)容 private String[] texts = null; // 菜單高度 private int height = 0; private View anchorView = null; /** * 默認(rèn)的構(gòu)造器 */ public MenuUtility() { // TODO Auto-generated constructor stub } /** * 帶Context的構(gòu)造器 * @param context */ public MenuUtility(Context context) { // TODO Auto-generated constructor stub this(context,null,null,0,null); } /** * 帶多參的構(gòu)造器 * @param context * @param imageRes * @param texts */ public MenuUtility(Context context,int[] imageRes,String[] texts,int height,View anchorView){ this.context = context; this.imageRes = imageRes; this.texts = texts; this.height = height; this.anchorView = anchorView; } /** * 設(shè)置圖片資源 * @param imageRes */ public void setImageRes(int[] imageRes){ this.imageRes = imageRes; } /** * 設(shè)置文字內(nèi)容 * @param texts */ public void setTexts(String[] texts){ this.texts = texts; } /** * 設(shè)置高度 * @param height */ public void setHeight(int height){ this.height = height; } /** * 設(shè)置顯示的位置 * @param anchor */ public void setAnchorView(View anchor){ anchorView = anchor; } /** * 獲取PulldownMenuView對(duì)象 * 以下拉的形式展現(xiàn)出來(lái)菜單 * @return */ public PulldownMenuView getPulldownMenuView(String currentItem){ PulldownMenuView menu = new PulldownMenuView(context); menu.setImageRes(imageRes); menu.setMenuText(texts); menu.setHeight(height); menu.setAnchorView(anchorView); menu.setCurrentItem(currentItem); menu.setBackground(R.drawable.navigation_bg); return menu; } /** * 獲取PulldownMenuView對(duì)象 * 以向上彈出的方式展現(xiàn)出來(lái)菜單 * @return */ public PulldownMenuView getPopupMenuView(){ PulldownMenuView menu = new PulldownMenuView(context); menu.setImageRes(imageRes); menu.setMenuText(texts); // menu.setLocation(Gravity.BOTTOM | Gravity.CENTER); menu.setAnimStyle(R.style.pulldown_in_out); menu.setBackground(R.drawable.navigation_bg); return menu; } }
既然是使用PopupWindow實(shí)現(xiàn)我們的效果,當(dāng)然了,它也可以以向上彈出的方式展現(xiàn)。在我這個(gè)示例中,需要它展現(xiàn)的位置是在頂部橫條下面展現(xiàn),所以設(shè)置:
menu.setAnchorView(anchorView);
另外,在MainActivity中需要設(shè)置它的顯示高度,在這里高度需要在頂部橫條和底部RadioGroup之間,這就需要我們獲取手機(jī)屏幕的高度減去頂部橫條的高度,再減去底部RadioGroup的高度,最后減去手機(jī)菜單欄的高度。在點(diǎn)擊某項(xiàng)菜單后,還需要將頂部中間文字和右邊三角圖片進(jìn)行相應(yīng)的變換。代碼如下所示:
package com.navigation.acitvity; import com.navigation.constant.ConstantCategoryMenu; import com.navigation.control.PulldownMenuView; import com.navigation.control.PulldownMenuView.OnMenuItemClickListener; import com.navigation.utility.DeviceUtility; import com.navigation.utility.MenuUtility; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; /** * Android實(shí)現(xiàn)下拉導(dǎo)航選擇菜單效果 * @Description: Android實(shí)現(xiàn)下拉導(dǎo)航選擇菜單效果 * @File: MainActivity.java * @Package com.navigation.acitvity * @Author Hanyonglu * @Date 2012-7-28 下午06:08:27 * @Version V1.0 */ public class MainActivity extends Activity { // 今日頭條LinearLayout private LinearLayout linearLayoutTopic = null; // 界面布局 private RelativeLayout layoutHeader = null; private LinearLayout layoutBottom = null; private FrameLayout layoutBody = null; // PulldownMenuView基本操作類(lèi) private MenuUtility menuUtility = null; // PulldownMenuView對(duì)象 private PulldownMenuView pullDownMenu = null; private TextView tvTopic = null; private ImageView ivTopic = null; private int height = 0; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 初始化 initViews(); } /** * 初始化 */ protected void initViews(){ ivTopic = (ImageView) findViewById(R.id.imageViewTopic); tvTopic = (TextView) findViewById(R.id.textViewTopic); linearLayoutTopic = (LinearLayout)findViewById(R.id.linearLayoutTopic); linearLayoutTopic.setOnClickListener(TopicOnClickListener); layoutHeader = (RelativeLayout) findViewById(R.id.layout_top_header); layoutBottom = (LinearLayout) findViewById(R.id.layout_bottom); layoutBody = (FrameLayout) findViewById(R.id.layout_body); height = DeviceUtility.getScreenSize(this)[1] - layoutHeader.getLayoutParams().height - layoutBottom.getLayoutParams().height - DeviceUtility.getStatusBarHeight(this); menuUtility = new MenuUtility( MainActivity.this, ConstantCategoryMenu.newsImageRes, ConstantCategoryMenu.newsMenuTexts, height,layoutHeader); } /** * 顯示PulldownMenuView */ protected void showPulldownMenu(){ pullDownMenu = menuUtility.getPulldownMenuView((String)tvTopic.getText()); ivTopic.setImageResource(R.drawable.ic_menu_trangle_up); } /** * 隱藏PulldownMenuView */ protected void hidePulldownMenu(){ pullDownMenu.releasePopupMenuView(); ivTopic.setImageResource(R.drawable.ic_menu_trangle_down); } // 頂部今日頭條事件監(jiān)聽(tīng)器 private OnClickListener TopicOnClickListener = new OnClickListener() { @Override public void onClick(View v) { // 開(kāi)始顯示下拉菜單 showPulldownMenu(); // TODO Auto-generated method stub pullDownMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override public void onMenuItemClick(AdapterView<?> parent, View view, int position) { // TODO Auto-generated method stub tvTopic.setText(ConstantCategoryMenu.newsMenuTexts[position]); layoutBody.setBackgroundResource(ConstantCategoryMenu.newsBodyRes[position]); } @Override public void hideMenu() { // TODO Auto-generated method stub hidePulldownMenu(); } }); pullDownMenu.show(); } }; }
我們?cè)讷@取MainActivity中頂部橫條和底部RadioGroup的高度時(shí)需要注意在布局文件中設(shè)置其相應(yīng)的layout_height,否則,我們是獲取不到其高度的。程序中間的主體部分是截取了幾張圖片,這個(gè)大家可以根據(jù)自己的需要設(shè)置成自己的數(shù)據(jù)格式。這點(diǎn)知道就可以了。
以上便是Android中實(shí)現(xiàn)下拉導(dǎo)航選擇菜單效果的實(shí)現(xiàn)過(guò)程,是在PopupWindow中嵌入GridView實(shí)現(xiàn),當(dāng)然也可以在PopupWindow中嵌入ListView等各種控件實(shí)現(xiàn)相應(yīng)的效果,也可以對(duì)PopupWindow實(shí)現(xiàn)各種和樣的變幻效果,具體過(guò)程這里就不再詳述了,有興趣的朋友我們可以一起探討。
源碼下載:下拉導(dǎo)航選擇菜單
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android制作微信app頂部menu菜單(ActionBar)
- Android App中DrawerLayout抽屜效果的菜單編寫(xiě)實(shí)例
- Android界面設(shè)計(jì)(APP設(shè)計(jì)趨勢(shì) 左側(cè)隱藏菜單右邊顯示content)
- Android實(shí)現(xiàn)頂部導(dǎo)航菜單左右滑動(dòng)效果
- Android滑動(dòng)優(yōu)化高仿QQ6.0側(cè)滑菜單(滑動(dòng)優(yōu)化)
- Android實(shí)現(xiàn)自定義滑動(dòng)式抽屜菜單效果
- android RecyclerView側(cè)滑菜單,滑動(dòng)刪除,長(zhǎng)按拖拽,下拉刷新上拉加載
- Android仿微信滑動(dòng)彈出編輯、刪除菜單效果、增加下拉刷新功能
- Android利用滑動(dòng)菜單框架實(shí)現(xiàn)滑動(dòng)菜單效果
- Android實(shí)現(xiàn)美團(tuán)APP的底部滑動(dòng)菜單
相關(guān)文章
android中DownloadManager實(shí)現(xiàn)版本更新,監(jiān)聽(tīng)下載進(jìn)度實(shí)例
本篇文章主要介紹了android中DownloadManager實(shí)現(xiàn)版本更新,監(jiān)聽(tīng)下載進(jìn)度實(shí)例。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03Android實(shí)現(xiàn)按鈕點(diǎn)擊效果
本文主要介紹了Android實(shí)現(xiàn)按鈕點(diǎn)擊效果:第一次點(diǎn)擊變色,第二次恢復(fù)。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02詳解React Native監(jiān)聽(tīng)Android回退按鍵與程序化退出應(yīng)用
這篇文章主要介紹了詳解React Native監(jiān)聽(tīng)Android回退按鍵與程序化退出應(yīng)用的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-09-09Android 彈出Dialog時(shí)隱藏狀態(tài)欄和底部導(dǎo)航欄的方法
這篇文章主要介紹了Android 彈出Dialog時(shí)隱藏狀態(tài)欄和底部導(dǎo)航欄的實(shí)例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07Android Chronometer控件實(shí)現(xiàn)計(jì)時(shí)器函數(shù)詳解
這篇文章主要為大家詳細(xì)介紹了Android Chronometer控件實(shí)現(xiàn)計(jì)時(shí)器函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-04-04Android簡(jiǎn)單封裝一個(gè)MVP基類(lèi)流程詳解
MVP是從經(jīng)典的模式MVC演變而來(lái),它們的基本思想有相通的地方:Controller/Presenter負(fù)責(zé)邏輯的處理,Model提供數(shù)據(jù),View負(fù)責(zé)顯示。下面這篇文章主要給大家介紹了關(guān)于Android從實(shí)現(xiàn)到封裝MVP的相關(guān)內(nèi)容,分享出來(lái)供大家參考學(xué)習(xí),下面話(huà)不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧2023-03-03Android發(fā)送GET與POST請(qǐng)求的DEMO詳解
本篇文章是對(duì)Android發(fā)送GET與POST請(qǐng)求的DEMO進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06Android開(kāi)發(fā)之Picasso通過(guò)URL獲取用戶(hù)頭像的圓形顯示
這篇文章主要介紹了android開(kāi)發(fā)之Picasso通過(guò)URL獲取用戶(hù)頭像的圓形顯示,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-06-06