摘要:需求分析在餓了么首頁中我們能看到這樣的布局如下圖。導(dǎo)航點(diǎn)是使用文件畫的,灰色為未選中,綠色為選中。因?yàn)槟J(rèn)顯示的是第一頁,所以我們默認(rèn)第一個(gè)的導(dǎo)航點(diǎn)是選中的。
1、需求分析
在餓了么首頁中我們能看到這樣的布局(如下圖)。紅框內(nèi)是一個(gè)可以左右滑動(dòng)的頁面,每一個(gè)頁面類似于九宮格,都有可供點(diǎn)擊圖標(biāo)。對于這樣的布局,我在網(wǎng)上找了很久都沒有找到相關(guān)的名稱,所以我這里暫時(shí)叫它導(dǎo)航頁吧。
最近公司的項(xiàng)目就要求我實(shí)現(xiàn)一個(gè)這樣的布局,但是我們的圖標(biāo)并不是想餓了么這樣是固定的,所以在餓了么的布局上還要加一個(gè)效果:在圖標(biāo)數(shù)目無法排滿兩行時(shí),就只顯示一行。比如說,我們每一頁最多可以顯示兩行和四列,當(dāng)圖標(biāo)的總數(shù)目小于或等于4個(gè)時(shí)就只顯示出一行,第二行就不要了。這樣頁面就不至于留出太多的空白。
先梳理一下我們要實(shí)現(xiàn)的效果:
大體的框架是一個(gè)可以左右滑動(dòng)的頁面;
每一頁為兩行四列的矩陣;
底部有和頁面數(shù)目相等的導(dǎo)航點(diǎn),且滑動(dòng)到某個(gè)頁面時(shí),相應(yīng)的導(dǎo)航點(diǎn)會(huì)改變顏色;
單選事件:選中圖標(biāo)后,圖標(biāo)變?yōu)橥耆煌该鳌?/p>
明白需求之后,我們穿越時(shí)空看看最后實(shí)現(xiàn)后的布局:
圖片資源大家可以在我源碼中找到。
2、實(shí)現(xiàn)思路我們已經(jīng)分析了需求,現(xiàn)在就來分析一下怎么實(shí)現(xiàn)。
必須事先說明一下,我的實(shí)現(xiàn)方法比較暴力,也比較占資源,所以大家要是有更好的方法的話歡迎留言告訴我,我們互相學(xué)習(xí)。
首先,這是一個(gè)左右滑動(dòng)的頁面,所以我們可以考慮使用ViewPager我們每個(gè)頁面有8個(gè)圖標(biāo),也就是8個(gè)item。在圖標(biāo)的數(shù)目在4以下時(shí)就只顯示第一行,所以布局上我們可以將四個(gè)item作為一行放置到橫向的線性布局中,當(dāng)?shù)诙袥]有圖標(biāo)時(shí)就讓它消失。
ViewPager中的每一頁的布局都是一樣,所以我們可以對其復(fù)用:將圖標(biāo)分組,每8個(gè)為一組(余下的不到八頁也歸為一組),每一組即為一頁。每次滑動(dòng)的頁面時(shí)就加載布局,填充圖標(biāo)和文字。
下面的導(dǎo)航點(diǎn)就比較簡單了,可以使用ViewPager的滑動(dòng)監(jiān)聽事件進(jìn)行監(jiān)聽,滑動(dòng)到選中的頁面時(shí)就改變導(dǎo)航點(diǎn)的顏色。
至于透明,我們只需要記錄圖標(biāo)的選中狀態(tài),然后改變透明度即可。
3、編寫布局接下來就讓我們創(chuàng)建項(xiàng)目,編寫頁面布局吧。
在Android Studio中創(chuàng)建一個(gè)NavigationPager項(xiàng)目,MainActivity的布局如下:
activity_main.xmlMainActivity的主布局是一個(gè)縱向的線性布局,上面一個(gè)ViewPager,下面一個(gè)橫向的線性布局,用于放置導(dǎo)航點(diǎn)。這里得說一下ViewPager的特性,在不指定特定高度的情況下,ViewPager的高度是默認(rèn)填充整個(gè)父布局的,我們顯然不希望這樣,畢竟我們還要分一行和兩行兩種情況呢。所以這里我在這里使用了一個(gè)可以自適應(yīng)高度的自定義ViewPager:
CustomViewPager/** * Created by Lindroid on 2017/3/20. * 自適應(yīng)高度的ViewPager */ public class CustomViewPager extends ViewPager { public CustomViewPager(Context context) { super(context); } public CustomViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = 0; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); int h = child.getMeasuredHeight(); if (h > height) height = h; } heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
頁面的布局(也就是ViewPager的子布局)可以拆分成兩個(gè)橫向排列的布局:
layout_line1.xml和layout_line2.xml分別為第一行和第二行的布局,下面是layout_line1.xml的布局。layout_line2.xml除了控件的id名不同之外,其他的都一樣,這里就不貼出來了。
好了,我們所需要的布局都已經(jīng)編寫完畢,下面就正式開始寫代碼了!
4、編寫代碼 4.1 創(chuàng)建Bean類創(chuàng)建一個(gè)NavigationItemBean類,用于存儲圖標(biāo)的圖片id、名稱和選中狀態(tài)等信息。
public class NavigationItemBean { private int iconID; private String iconName; private boolean isSelected; public NavigationItemBean(int iconID, String iconName) { this.iconID = iconID; this.iconName = iconName; } public boolean isSelected() { return isSelected; } public void setSelected(boolean selected) { isSelected = selected; } public int getIconID() { return iconID; } public void setIconID(int iconID) { this.iconID = iconID; } public String getIconName() { return iconName; } public void setIconName(String iconName) { this.iconName = iconName; } }4.2 設(shè)置圖標(biāo)資源
為了提高效率,我在初始化控件時(shí)使用了ButterKnife,大家需要它的jar包的話也可以從我的工程中復(fù)制粘貼。
public class MainActivity extends AppCompatActivity { @Bind(R.id.vp_navigation) CustomViewPager vpNavigation; @Bind(R.id.ll_dots) LinearLayout llDots; private NavigationAdapter adapter; private ListitemBeanList = new ArrayList<>(); private List dots = new ArrayList<>(); //圖標(biāo)id數(shù)組 private int[] icons = {R.mipmap.phone, R.mipmap.browser, R.mipmap.messages, R.mipmap.contacts, R.mipmap.camera, R.mipmap.gallery, R.mipmap.calendar, R.mipmap.calculator, R.mipmap.settings, R.mipmap.mail, R.mipmap.maps, R.mipmap.music, R.mipmap.movie}; //圖標(biāo)名稱數(shù)組 private String[] names = {"電話", "瀏覽器", "信息", "聯(lián)系人", "照相", "圖庫", "日歷", "計(jì)算器", "設(shè)置", "郵箱", "地圖", "音樂", "電影"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); initData(); } private void initData() { for (int i = 0; i < icons.length; i++) { itemBeanList.add(new NavigationItemBean(icons[i], names[i])); } adapter = new NavigationAdapter(this, itemBeanList, this); vpNavigation.setAdapter(adapter); } }
先將圖標(biāo)的id和名稱存儲到兩個(gè)數(shù)組中,再遍歷數(shù)組將資源添加到集合中。
4.3 創(chuàng)建適配器這一步應(yīng)該是整個(gè)項(xiàng)目中最難的一步了,所以要打起精神來了。先看下面的代碼:
public class NavigationAdapter extends PagerAdapter { @Bind(R.id.iv_icon1) ImageView ivIcon1; @Bind(R.id.tv_name1) TextView tvName1; @Bind(R.id.ll_item1) LinearLayout llItem1; @Bind(R.id.iv_icon2) ImageView ivIcon2; @Bind(R.id.tv_name2) TextView tvName2; @Bind(R.id.ll_item2) LinearLayout llItem2; @Bind(R.id.iv_icon3) ImageView ivIcon3; @Bind(R.id.tv_name3) TextView tvName3; @Bind(R.id.ll_item3) LinearLayout llItem3; @Bind(R.id.iv_icon4) ImageView ivIcon4; @Bind(R.id.tv_name4) TextView tvName4; @Bind(R.id.ll_item4) LinearLayout llItem4; @Bind(R.id.iv_icon5) ImageView ivIcon5; @Bind(R.id.tv_name5) TextView tvName5; @Bind(R.id.ll_item5) LinearLayout llItem5; @Bind(R.id.iv_icon6) ImageView ivIcon6; @Bind(R.id.tv_name6) TextView tvName6; @Bind(R.id.ll_item6) LinearLayout llItem6; @Bind(R.id.iv_icon7) ImageView ivIcon7; @Bind(R.id.tv_name7) TextView tvName7; @Bind(R.id.ll_item7) LinearLayout llItem7; @Bind(R.id.iv_icon8) ImageView ivIcon8; @Bind(R.id.tv_name8) TextView tvName8; @Bind(R.id.ll_item8) LinearLayout llItem8; @Bind(R.id.ll_line2) LinearLayout llLine2; private Context context; private ListitemBeanList; private List itemViews; int pages; //總頁數(shù) private View pageView; private View.OnClickListener onClickListener; public NavigationAdapter(Context context, List itemBeanList, View.OnClickListener onClickListener) { this.context = context; this.itemBeanList = itemBeanList; this.onClickListener = onClickListener; itemViews = new ArrayList<>(); initView(itemBeanList); } /** * 初始化ViewPager的頁面布局 * @param list */ private void initView(List list) { itemViews.clear(); //計(jì)算ViewPager的頁數(shù) pages = list.size() / 9; pages = pages + 1; for (int i = 0; i < pages; i++) { pageView = View.inflate(context, R.layout.page_navigation, null); ButterKnife.bind(this, pageView); setPagerViewData(i); itemViews.add(pageView); } } /** * 根據(jù)頁碼來填充數(shù)據(jù) * @param pageNum */ public void setPagerViewData(int pageNum) { if (itemBeanList.size() > pageNum * 8 + 0) { llItem1.setVisibility(View.VISIBLE); tvName1.setText(itemBeanList.get(pageNum * 8 + 0).getIconName()); ivIcon1.setBackgroundResource(itemBeanList.get(pageNum * 8 + 0).getIconID()); setIconAlpha(itemBeanList.get(pageNum * 8 + 0).isSelected(), ivIcon1); } else { llItem1.setVisibility(View.INVISIBLE); } if (itemBeanList.size() > pageNum * 8 + 1) { llItem2.setVisibility(View.VISIBLE); tvName2.setText(itemBeanList.get(pageNum * 8 + 1).getIconName()); ivIcon2.setBackgroundResource(itemBeanList.get(pageNum * 8 + 1).getIconID()); setIconAlpha(itemBeanList.get(pageNum * 8 + 1).isSelected(), ivIcon2); } else { llItem2.setVisibility(View.INVISIBLE); } if (itemBeanList.size() > pageNum * 8 + 2) { llItem3.setVisibility(View.VISIBLE); tvName3.setText(itemBeanList.get(pageNum * 8 + 2).getIconName()); ivIcon3.setBackgroundResource(itemBeanList.get(pageNum * 8 + 2).getIconID()); setIconAlpha(itemBeanList.get(pageNum * 8 + 2).isSelected(), ivIcon3); } else { llItem3.setVisibility(View.INVISIBLE); } if (itemBeanList.size() > pageNum * 8 + 3) { llItem4.setVisibility(View.VISIBLE); tvName4.setText(itemBeanList.get(pageNum * 8 + 3).getIconName()); ivIcon4.setBackgroundResource(itemBeanList.get(pageNum * 8 + 3).getIconID()); setIconAlpha(itemBeanList.get(pageNum * 8 + 3).isSelected(), ivIcon4); } else { llItem4.setVisibility(View.INVISIBLE); } if (itemBeanList.size() > pageNum * 8 + 4) { llItem5.setVisibility(View.VISIBLE); tvName5.setText(itemBeanList.get(pageNum * 8 + 4).getIconName()); ivIcon5.setBackgroundResource(itemBeanList.get(pageNum * 8 + 4).getIconID()); setIconAlpha(itemBeanList.get(pageNum * 8 + 4).isSelected(), ivIcon5); } else { llItem5.setVisibility(View.INVISIBLE); llLine2.setVisibility(View.GONE); } if (itemBeanList.size() > pageNum * 8 + 5) { llItem6.setVisibility(View.VISIBLE); tvName6.setText(itemBeanList.get(pageNum * 8 + 5).getIconName()); ivIcon6.setBackgroundResource(itemBeanList.get(pageNum * 8 + 5).getIconID()); setIconAlpha(itemBeanList.get(pageNum * 8 + 5).isSelected(), ivIcon6); } else { llItem6.setVisibility(View.INVISIBLE); } if (itemBeanList.size() > pageNum * 8 + 6) { llItem7.setVisibility(View.VISIBLE); tvName7.setText(itemBeanList.get(pageNum * 8 + 6).getIconName()); ivIcon7.setBackgroundResource(itemBeanList.get(pageNum * 8 + 6).getIconID()); setIconAlpha(itemBeanList.get(pageNum * 8 + 6).isSelected(), ivIcon7); } else { llItem7.setVisibility(View.INVISIBLE); } if (itemBeanList.size() > pageNum * 8 + 7) { llItem8.setVisibility(View.VISIBLE); tvName8.setText(itemBeanList.get(pageNum * 8 + 7).getIconName()); ivIcon8.setBackgroundResource(itemBeanList.get(pageNum * 8 + 7).getIconID()); setIconAlpha(itemBeanList.get(pageNum * 8 + 7).isSelected(), ivIcon8); } else { llItem8.setVisibility(View.INVISIBLE); } } public void setIconAlpha(boolean isSelected, ImageView imageView) { if (isSelected) { imageView.setAlpha(1.0f); } else { imageView.setAlpha(0.4f); } } @Override public int getCount() { return pages; } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(itemViews.get(position)); return itemViews.get(position); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } }
代碼有點(diǎn)長,但其實(shí)不難理解。首先我們創(chuàng)建一個(gè)NavigationAdapter繼承于ViewPager專用的PageAdapter,并重寫其中的幾個(gè)方法。這里就要注意一個(gè)小地方了,getCount方法返回的是ViewPager的item數(shù)目,也就是頁數(shù),而不是圖標(biāo)的數(shù)目,可千萬不能搞錯(cuò)了!
下面我就講解一下比較重要的方法。首先是初始化ViewPager頁面布局的方法initView:
private void initView(Listlist) { itemViews.clear(); //計(jì)算ViewPager的頁數(shù) pages = list.size() / 9; pages = pages + 1; for (int i = 0; i < pages; i++) { pageView = View.inflate(context, R.layout.page_navigation, null); ButterKnife.bind(this, pageView); setPagerViewData(i); itemViews.add(pageView); } }
第4和第5行的代碼是根據(jù)圖標(biāo)的數(shù)目來計(jì)算ViewPager的頁數(shù),而for循環(huán)則是有多少頁我們就調(diào)用多少次View.inflate方法去創(chuàng)建布局。這也是ButterKnife.bind(this, pageView)要在for循環(huán)中執(zhí)行的原因:我們使用的雖然都是同一個(gè)布局文件,但實(shí)際每次循環(huán)都會(huì)創(chuàng)建一個(gè)新的布局。
setPagerViewData方法則是給頁面中的每個(gè)item填充數(shù)據(jù)。首先判斷集合中的某一位是否有數(shù)據(jù),有的話則設(shè)置圖片和文字,反之則隱藏item。里面的代碼基本都一個(gè)樣子,我就摘錄其中“最特別”的一段了:
if (itemBeanList.size() > pageNum * 8 + 4) { llItem5.setVisibility(View.VISIBLE); tvName5.setText(itemBeanList.get(pageNum * 8 + 4).getIconName()); ivIcon5.setBackgroundResource(itemBeanList.get(pageNum * 8 + 4).getIconID()); setIconAlpha(itemBeanList.get(pageNum * 8 + 4).isSelected(), ivIcon5); } else { llItem5.setVisibility(View.INVISIBLE); llLine2.setVisibility(View.GONE); //t圖標(biāo)數(shù)不大于4個(gè)時(shí)讓第二行消失 }
如果你對于initView方法中for循環(huán)從0開始(頁碼的取值從0開始)而不是從1開始感到不解,那么看了setPagerViewData方法之后相信你就會(huì)懂了。頁碼為0時(shí),第一頁的第一個(gè)item取到的正好是集合的0位元素;頁碼為1時(shí),第二頁的第一個(gè)item則是集合中的第8位(1x8+1)元素,這樣,我們就可以根據(jù)具體的頁碼來將集合中的元素填充到頁面中。這里別忘了還有高度適應(yīng)的問題。回頭看看我摘出來的這段代碼,當(dāng)集合長度不大于4時(shí),我們不僅要隱藏第五個(gè)item,而且要讓第二行的布局消失,這時(shí),ViewPager的高度就只有一行了。但你肯定會(huì)問,第一頁時(shí)去掉第二行沒什么,可以到了第二頁時(shí)如果集合元素排不到第二行,第二行也會(huì)消失嗎?答案是不會(huì)的。ViewPager默認(rèn)所有頁面的高度都是一致的,就算你在第二頁就去掉了第二行,它的高度也不會(huì)隨著改變。
4.4 設(shè)置導(dǎo)航點(diǎn)在MainActivity中,我們創(chuàng)建繪制導(dǎo)航點(diǎn)的方法。導(dǎo)航點(diǎn)是使用xml文件畫的,灰色為未選中,綠色為選中。
private Listdots = new ArrayList<>(); /** * 繪制導(dǎo)航點(diǎn) */ private void initDot() { for (int i = 0; i < (itemBeanList.size() / 9 + 1); i++) { Log.e("Tag", itemBeanList.size() + ""); ImageView imageView = new ImageView(this); //創(chuàng)建一個(gè)ImageView來放置圓點(diǎn),并確定ImageView的寬高 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( 20, 20); params.leftMargin = 10; params.rightMargin = 10; params.topMargin = 5; params.bottomMargin = 10; imageView.setLayoutParams(params); dots.add(imageView); //由于剛進(jìn)去引導(dǎo)頁時(shí)出現(xiàn)的是第一個(gè)引導(dǎo)頁,故此時(shí)的導(dǎo)航點(diǎn)設(shè)置為紅色 if (i == 0) { dots.get(i).setBackgroundResource(R.drawable.dot_green); } else { dots.get(i).setBackgroundResource(R.drawable.dot_gray); } llDots.addView(imageView); } }
導(dǎo)航點(diǎn)的父布局是LinearLayout,所以我們使用LinearLayout中的LayoutParams給導(dǎo)航點(diǎn)設(shè)置上下左右的邊距。在onCreate中調(diào)用該方法就可以繪制導(dǎo)航點(diǎn)了。因?yàn)閂iewPager默認(rèn)顯示的是第一頁,所以我們默認(rèn)第一個(gè)的導(dǎo)航點(diǎn)是選中的。
除此之外,我們還需要讓導(dǎo)航點(diǎn)起到導(dǎo)航的作用。這時(shí)候就可以去調(diào)用ViewPager的頁面滑動(dòng)監(jiān)聽了:
/** * 滑動(dòng)監(jiān)聽事件 */ vpNavigation.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { Log.e("Tag", "position=" + position); for (int i = 0; i < dots.size(); i++) { if (i == position) { dots.get(i).setBackgroundResource(R.drawable.dot_green); } else { dots.get(i).setBackgroundResource(R.drawable.dot_gray); } } } @Override public void onPageScrollStateChanged(int state) { } });
在選中某個(gè)頁面時(shí)就將對應(yīng)的導(dǎo)航點(diǎn)改為綠色就可以了。
4.5 圖標(biāo)的點(diǎn)擊事件頁面布局中的控件都是在適配器NavigationAdapter中初始化的,為了在MainActivity中能夠?qū)崿F(xiàn)它們的點(diǎn)擊事件,我們在NavigationAdapter的構(gòu)造方法中傳入一個(gè)View.onClickListener的對象作為參數(shù),只需在MainActivity繼承View.OnClickListener接口,在創(chuàng)建NavigationAdapter時(shí)傳入this即可。
當(dāng)然,我們還需要在NavigationAdapter中讓需要實(shí)現(xiàn)點(diǎn)擊事件的控件調(diào)用setOnClickListener方法:
private void initListener() { llItem1.setOnClickListener(onClickListener); llItem2.setOnClickListener(onClickListener); llItem3.setOnClickListener(onClickListener); llItem4.setOnClickListener(onClickListener); llItem5.setOnClickListener(onClickListener); llItem6.setOnClickListener(onClickListener); llItem7.setOnClickListener(onClickListener); llItem8.setOnClickListener(onClickListener); }
大家想一想,initListener方法應(yīng)該在哪里調(diào)用呢?這里有一個(gè)坑,由于ViewPager的頁面是一頁一頁地繪制的,所以注冊控件的點(diǎn)擊事件也應(yīng)該在for循環(huán)中,為每一頁的控件都注冊一遍:
for (int i = 0; i < pages; i++) { pageView = View.inflate(context, R.layout.page_navigation, null); ButterKnife.bind(this, pageView); setPagerViewData(i); itemViews.add(pageView); initListener(); }
好了,現(xiàn)在可以到MainActivity中實(shí)現(xiàn)監(jiān)聽事件了:
@Override public void onClick(View v) { int pageNum = vpNavigation.getCurrentItem(); Log.e("Tag", "viewPager.getCurrentItem()=" + vpNavigation.getCurrentItem()); switch (v.getId()) { case R.id.ll_item1: Toast.makeText(this, itemBeanList.get(pageNum * 8 + 0).getIconName(), Toast.LENGTH_SHORT).show(); initSelected(); itemBeanList.get(pageNum * 8 + 0).setSelected(true); adapter.refresh(itemBeanList); break; case R.id.ll_item2: Toast.makeText(this, itemBeanList.get(pageNum * 8 + 1).getIconName(), Toast.LENGTH_SHORT).show(); initSelected(); itemBeanList.get(pageNum * 8 + 1).setSelected(true); adapter.refresh(itemBeanList); break; case R.id.ll_item3: Toast.makeText(this, itemBeanList.get(pageNum * 8 + 2).getIconName(), Toast.LENGTH_SHORT).show(); initSelected(); itemBeanList.get(pageNum * 8 + 2).setSelected(true); adapter.refresh(itemBeanList); break; case R.id.ll_item4: Toast.makeText(this, itemBeanList.get(pageNum * 8 + 3).getIconName(), Toast.LENGTH_SHORT).show(); initSelected(); itemBeanList.get(pageNum * 8 + 3).setSelected(true); adapter.refresh(itemBeanList); break; case R.id.ll_item5: Toast.makeText(this, itemBeanList.get(pageNum * 8 + 4).getIconName(), Toast.LENGTH_SHORT).show(); initSelected(); itemBeanList.get(pageNum * 8 + 4).setSelected(true); adapter.refresh(itemBeanList); break; case R.id.ll_item6: Toast.makeText(this, itemBeanList.get(pageNum * 8 + 5).getIconName(), Toast.LENGTH_SHORT).show(); initSelected(); itemBeanList.get(pageNum * 8 + 5).setSelected(true); adapter.refresh(itemBeanList); break; case R.id.ll_item7: Toast.makeText(this, itemBeanList.get(pageNum * 8 + 6).getIconName(), Toast.LENGTH_SHORT).show(); initSelected(); itemBeanList.get(pageNum * 8 + 6).setSelected(true); adapter.refresh(itemBeanList); break; case R.id.ll_item8: Toast.makeText(this, itemBeanList.get(pageNum * 8 + 7).getIconName(), Toast.LENGTH_SHORT).show(); initSelected(); itemBeanList.get(pageNum * 8 + 7).setSelected(true); adapter.refresh(itemBeanList); break; default: break; } } /** * 初始化圖標(biāo)的選擇狀態(tài),全部設(shè)置為未選中狀態(tài) */ private void initSelected() { for (int i = 0; i < itemBeanList.size(); i++) { itemBeanList.get(i).setSelected(false); } }
刷新Adapter時(shí)我是重新調(diào)用了initView方法,并且傳入了修改后的數(shù)據(jù)源。下面是在Adapter中刷新的方法:
public void refresh(ListitemBeanList){ initView(itemBeanList); notifyDataSetChanged(); }
運(yùn)行一下,點(diǎn)擊,咦,怎么沒有反應(yīng)呢?PageAdapter這里有一個(gè)坑了:notifyDataSetChanged只有在ViewPager的頁數(shù)發(fā)生變化才會(huì)刷新頁面,單是某一個(gè)頁面的數(shù)據(jù)發(fā)生變化時(shí)是沒用的。但是不用著急,我們可以重寫getItemPosition方法,讓其返回POSITION_NONE,強(qiáng)迫viewpager重繪所有的頁面。
/** * 使Adapter能夠刷新布局 */ private int mChildCount = 0; @Override public void notifyDataSetChanged() { mChildCount = getCount(); super.notifyDataSetChanged(); } @Override public int getItemPosition(Object object) { if (mChildCount > 0) { mChildCount--; return POSITION_NONE; } return super.getItemPosition(object); }
運(yùn)行一下,點(diǎn)擊,發(fā)現(xiàn)可以完美實(shí)現(xiàn)我們要的效果了。
4.6 雙擊取消選中實(shí)現(xiàn)雙擊取消選中的效果并不難,我們只需在點(diǎn)擊每一個(gè)圖標(biāo)之前都判斷一下當(dāng)前的選擇狀態(tài),如果當(dāng)前為選中的狀態(tài),則將狀態(tài)改為未選中,反之,則改為選中。示例代碼如下:
if (itemBeanList.get(pageNum * 8 + 0).isSelected()) { initSelected(); itemBeanList.get(pageNum * 8 + 0).setSelected(false); } else { initSelected(); itemBeanList.get(pageNum * 8 + 0).setSelected(true); }
我在代碼中只設(shè)置了前面兩項(xiàng),大家如果想實(shí)現(xiàn)所有圖標(biāo)的雙擊選中事件的話就自己動(dòng)一下手吧!
5、總結(jié)這個(gè)功能我前前后后花了不少時(shí)間,在參考別人代碼的基礎(chǔ)上總算是實(shí)現(xiàn)了,水平有限,如果博客中有錯(cuò)漏的地方,歡迎批評指正。我的寫法還是太過簡單粗暴,不夠精巧,而且對資源的占用也比較大,如果你有更好的方法,歡迎交流學(xué)習(xí)。聽說ViewPager+GridVie也可以實(shí)現(xiàn)同樣的效果,接下來我再研究一下,看能不能再寫一篇博客吧!
最后是源碼下載地址:
GitHub
CSDN
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67144.html
摘要:無論是跑馬燈新聞標(biāo)題還是餓了么的導(dǎo)航欄,它們的作用都是一樣的,那就是復(fù)用有限的屏幕空間,展示更為豐富的內(nèi)容。最后附上源碼的地址參考文章之的簡單使用仿淘寶首頁的淘寶頭條垂直滾動(dòng)仿餓了么首頁導(dǎo)航欄 在淘寶App的首頁中間位置,有一塊小小的地方在不知疲倦地循壞滾動(dòng)著頭條標(biāo)題(見下圖的紅框區(qū)域),這樣的設(shè)計(jì)無疑能夠在有限的手機(jī)屏幕上展示更豐富的內(nèi)容。而實(shí)現(xiàn)這一功能需要用到的控件就是我在上一篇文...
閱讀 3101·2021-11-24 11:14
閱讀 3570·2021-11-22 15:22
閱讀 3236·2021-09-27 13:36
閱讀 755·2021-08-31 14:29
閱讀 1354·2019-08-30 15:55
閱讀 1813·2019-08-29 17:29
閱讀 1168·2019-08-29 16:24
閱讀 2463·2019-08-26 13:48