android 面包屑控件,android面包屑導航欄的實現

本文介绍了面包屑导航的实现原理,通过FragmentTransaction和FragmentManager来管理页面层级,并在用户点击时直接返回相应级别。同时,针对评论中提到的回退后显示空白页的问题,提出了修改建议:不将第一个Fragment加入回退栈,并手动添加根Fragment的标题。完整示例代码已在GitHub上分享。
摘要由CSDN通过智能技术生成

面包屑導航的效果如下:

ZmlsZTovLy9DOlxVc2Vyc1x4dWRkXEFwcERhdGFcUm9hbWluZ1xUZW5jZW50XFVzZXJzXDEyMDgwMzY2M1xRUVxXaW5UZW1wXFJpY2hPbGVcSSR+RTVQOE0wX18oW1pIRUtPSVtCMUUucG5n

cabc0412da49cb3e6a334169a1af7e09.png

點擊面包屑上標藍的文字,可以直接返回到對應的級別。比如點擊“第2層”,就能直接返回到第2層下的目錄,而無須依次點返回。

面包屑導航的原理是通過FragmentTransaction去實現的,下面簡單介紹一下實現原理。

頁面分為兩部分:頂部的自定義導航欄view和下方的ListFragment,點擊fragment的item會進入下一層ListFragment。

自定義view我們暫且稱為CrumbView,它需要繼承HorizontalScrollView以擁有可以左右滾動的效果,同時要實現FragmentManager的OnBackStackChangedListener接口,這樣當fragment棧發生變化時,CrumbView就能收到通知並更新導航欄文字。

每次FragmentTransaction在執行replace/add fragment的操作時,需要調用setBreadCrumbTitle()方法設置面包屑的標題,同時需要將每次的操作都addToBackStack(),這樣在CrumbView中才能調用FragmentManager的getBackStackEntryAt()方法得到這個操作並取標題並顯示在標題欄上。

關鍵代碼如下:

CrumbView中收到OnBackStackChangedListener的回調時更新面包屑的代碼:

private void updateCrumbs() {

// 嵌套的fragment數量

int numFrags = mFragmentManager.getBackStackEntryCount();

// 面包屑的數量

int numCrumbs = mContainer.getChildCount();

for(int i = 0; i < numFrags; i++){

final FragmentManager.BackStackEntry backStackEntry = mFragmentManager.getBackStackEntryAt(i);

if(i < numCrumbs){

View view = mContainer.getChildAt(i);

Object tag = view.getTag();

if(tag != backStackEntry){

for(int j = i; j < numCrumbs; j++){

mContainer.removeViewAt(i);

}

numCrumbs = i;

}

}

if(i >= numCrumbs){

View itemView = LayoutInflater.from(getContext()).inflate(R.layout.crumb_item_layout, null);

TextView tv = (TextView) itemView.findViewById(R.id.crumb_name);

tv.setText(backStackEntry.getBreadCrumbTitle());

itemView.setTag(backStackEntry);

itemView.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

FragmentManager.BackStackEntry bse;

if (v.getTag() instanceof FragmentManager.BackStackEntry) {

bse = (FragmentManager.BackStackEntry) v.getTag();

mFragmentManager.popBackStack(bse.getId(), 0);

} else {

//全部回退

int count = mFragmentManager.getBackStackEntryCount();

if (count > 0) {

bse = mFragmentManager.getBackStackEntryAt(0);

mFragmentManager.popBackStack(bse.getId(), 0);

}

}

}

});

mContainer.addView(itemView);

}

}

numCrumbs = mContainer.getChildCount();

while(numCrumbs > numFrags){

mContainer.removeViewAt(numCrumbs - 1);

numCrumbs--;

}

//調整可見性

for (int i = 0; i < numCrumbs; i++) {

final View child = mContainer.getChildAt(i);

// 高亮

highLightIndex(child, !(i < numCrumbs - 1));

}

// 滑動到最后一個

post(new Runnable() {

@Override

public void run() {

fullScroll(ScrollView.FOCUS_RIGHT);

}

});

}

點擊fragment的item進入下一層ListFragment時的代碼:

@Override

public void onListItemClick(ListView l, View v, int position, long id) {

FragmentTransaction ft = mFragmentManager.beginTransaction();

ft.setBreadCrumbTitle(getString(R.string.crumb_title, mLevel + 1));

ft.replace(R.id.frag_container, MyFragment.getInstance(mLevel + 1));

ft.addToBackStack(null);

ft.commitAllowingStateLoss();

}

完整的demo已上傳至gitHub:

https://github.com/whsdu929/CrumbView.git

====================================================================================

有朋友評論說當fragment回退完后,會顯示空白的activity,解決方案是不要把第一個fragment addToBackStack:

activity里首次加載fragment時注釋這一行

//ft.addToBackStack(null);

然后在CrumbView里手動加上第一個fragment的標題

public void setActivity(final FragmentActivity activity, String rootTitle){

//手動把root fragment的標題加上

View itemView = LayoutInflater.from(getContext()).inflate(R.layout.crumb_item_layout, null);

final TextView tv = (TextView) itemView.findViewById(R.id.crumb_name);

tv.setText(rootTitle);

tv.setTextColor(LIGHT_COLOR);

itemView.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

//全部回退

FragmentManager.BackStackEntry bse = mFragmentManager.getBackStackEntryAt(0);

mFragmentManager.popBackStack(bse.getId(), 0);

tv.setTextColor(LIGHT_COLOR);

}

});

LinearLayout rootContainer = new LinearLayout(getContext());

......

rootContainer.addView(itemView);

rootContainer.addView(mContainer);

addView(rootContainer);

......

}

这个扩展允许你以面包屑的方式浏览任何URL。 描述: ========= 这个扩展允许用户以类似面包屑的方式浏览任何URL。用户可以选择两种导航选项:面包屑风格或文件夹风格。请参阅截图,了解每个示例。该扩展程序允许在子域级别(code.google.com => google.com),路径级别(google.com/search => google.com)或两者的混合(chrome.google.com/extensions = > google.com),包括Ajax网站(example.com/#ajax-state => example.com)。除此之外,如果还没有可用的其他关联标记,则当前免费版本中的扩展将重写Amazon.com的链接以包含Amazon关联标记。亚马逊品牌名称是Amazon.com的财产。此扩展程序不与商标所有者关联或由其赞助。 GitHub上的Breadcrumb Navigator主题工具包: ================================== 对于所有那些不喜欢扩展附带的主题的人 => https://github.com/tomayac/Breadcrumb-Navigator-Theming-Kit 如果您已完成主题,请发送给我(steiner.thomasREMOVE_THIS@gmail.com)CSS文件,我可以在下一个版本的扩展中包含您的主题。 获奖情况: ====== Breadcrumb Navigator已通过Softpedia测试: => http://mac.softpedia.com/get/Internet-Utilities/Breadcrumb-Navigator.shtml 它被授予Softpedia“100%清洁”奖。 更新日志: ======== * 1.1.0: - 新功能:在中间点击新标签打开面包屑或按住CTRL键。 - 新选项:在后台或前台打开新选项卡。 * 1.0.4: - 次要代码重组。 * 1.0.3: - 改变了弹出窗口的行为,点击后立即关闭。 - 修复了亚马逊代码中的错误。抱歉。 * 1.0.2: - 修正了每次显示更新通知的错误。抱歉。 * 1.0.1: - 感谢@russenreaktor两个新的轻量级主题可用:简单的蓝色和简单的白色 - 增加了德语本地化 * 1.0.0: - 增加了一个新的主题。 - 在Ajax网站上启用面包屑导航。 - 不幸的是Omnibar不能被修改。最接近修改Omnibar的是创建一个Infobar,但是,这只能在Chrome的Dev Channel上使用。 * 0.1.0: - 初始发行。 支持语言:Deutsch,English (United States)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值