Android底部导航布局封装
来源:互联网 发布:德芙的含义 知乎 编辑:程序博客网 时间:2024/04/28 22:43
现在市面上的APP大多数都是分为上中下三个层次,上层为标题导航和一些菜单功能;中层为内容层,可以上下左右滑动展示丰富的内容;下层就是功能切换层;今天我要说的就是下层的封装。在做APP开发时,遇到过很多APP都是有底部导航的,开始都是分开慢慢的写一个一个的功能选项,然后在activity中一个一个的获取,并设置状态那些,少说也要几百行代码,真乃体力活啊,但是作为“懒惰”的程序猿,我们不想每次都是cv战士,所以就把这一块功能封装了一下,然后每次要用的时候集成就很简单了,来看看效果和集成代码:
1、真机效果:
2、gif效果:
3、集成代码如下:
tabLayoutView.setDataSource(titles, imgs, 0); tabLayoutView.setImageStyle(25, 25); tabLayoutView.setTextStyle(12, R.color.color_999999,R.color.color_ff78a3); tabLayoutView.initDatas(); setDots(); tabLayoutView.setOnItemOnclickListener(new TabLayoutView.OnItemOnclickListener() { @Override public void onItemClick(int index) { viewPager.setCurrentItem(index, true); } });
设置显示圆点的代码为:
tabLayoutView.setDotsCount(2, 3);其中2表示显示的索引位置,3表示的是显示的个数。
这样就集成了底部功能导航了。
一:还是老规矩先说说算法(其实也不是算法,就是很简单的动态布局)
1、首先集成线性布局,并设置为横向排列
2、然后根据功能的个数添加相应个数的相对布局到线性布局中,并设置相对布局的宽度都一样。
3、再用一个线性布局,此时为纵向布局包裹,把图标和功能标题添加到里面,然后再把这个纵向布局添加到相对布局中,并居中。
4、在添加小圆点到相对布局中,并设置其位置为相对布局中纵向布局的右上角。
5、然后就是给相对布局添加点击事件,并暴露回调接口,设置小圆点显示的方法等。
这样就实现了底部导航功能了。
二:封装代码如下(TabLayoutView.java)
package com.ywl5320.bottomnavtabs;import android.content.Context;import android.util.AttributeSet;import android.view.Gravity;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.RelativeLayout;import android.widget.TextView;import java.util.ArrayList;import java.util.List;/** * Created by ywl on 2016/11/2. */public class TabLayoutView extends LinearLayout{ private Context context; private String[] titles; //要显示的标题 private int[] imgs; //图标 private int imgwidth; private int imgheight; private int txtsize; //标题大小 private int txtColor; //标题未选中颜色 private int txtSelectedColor; //选择颜色 private List<TextView> textViews; //保存标题 private List<ImageView> imageViews; //保存图片 private List<TextView> tvDots;//保存圆点 private int currentIndex = 0; private OnItemOnclickListener onItemOnclickListener; public TabLayoutView(Context context) { this(context, null); } public TabLayoutView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TabLayoutView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; } public void setOnItemOnclickListener(OnItemOnclickListener onItemOnclickListener) { this.onItemOnclickListener = onItemOnclickListener; } /** * 设置标题、图片和当前选中的条目 * @param tabtxts * @param imgs * @param currentIndex */ public void setDataSource(String[] tabtxts, int[] imgs, int currentIndex) { this.titles = tabtxts; this.imgs = imgs; this.currentIndex = currentIndex; } /** * 设置图标大小 * @param imgwidth * @param imgheight */ public void setImageStyle(int imgwidth, int imgheight) { this.imgwidth = dip2px(context, imgwidth); this.imgheight = dip2px(context, imgheight); } /** * 设置标题颜色 * @param txtsize * @param txtColor * @param txtSelectedColor */ public void setTextStyle(int txtsize, int txtColor, int txtSelectedColor) { this.txtsize = txtsize; this.txtColor = txtColor; this.txtSelectedColor = txtSelectedColor; } /** * 动态布局 * 1、外层为横向线下布局 * 2、动态添加相对布局,平分父布局,使宽度一致,添加到横向布局中 * 3、总线布局添加图标和标题,并添加到相对布局中 * 4、添加圆点到相对布局中,并设置在3的右上角 */ public void initDatas() { textViews = new ArrayList<>(); imageViews = new ArrayList<>(); tvDots = new ArrayList<>(); setOrientation(HORIZONTAL); LayoutParams lp = new LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT); lp.weight = 1; lp.gravity = Gravity.CENTER; LayoutParams imglp = new LayoutParams(imgwidth, imgheight); imglp.gravity = Gravity.CENTER; LayoutParams txtlp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); txtlp.gravity = Gravity.CENTER; RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); rlp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); int size = titles.length; for(int i = 0; i < size; i++) { ImageView imageView = new ImageView(context); imageView.setLayoutParams(imglp); imageView.setImageResource(imgs[i]); imageView.setScaleType(ImageView.ScaleType.FIT_XY); TextView textView = new TextView(context); textView.setText(titles[i]); textView.setLayoutParams(txtlp); textView.setTextSize(txtsize); LinearLayout cly = new LinearLayout(context); cly.setId(i + 100); cly.setGravity(Gravity.CENTER); cly.setOrientation(VERTICAL); cly.setLayoutParams(imglp); cly.addView(imageView); RelativeLayout prl = new RelativeLayout(context); RelativeLayout.LayoutParams rlDot = new RelativeLayout.LayoutParams(dip2px(context, 18), dip2px(context, 18)); rlDot.addRule(RelativeLayout.RIGHT_OF, cly.getId()); rlDot.addRule(RelativeLayout.ABOVE,cly.getId()); rlDot.setMargins( -dip2px(context, 8), 0, 0, -dip2px(context, 15)); TextView tvDot = new TextView(context); tvDot.setText("0"); tvDot.setTextSize(10); tvDot.setGravity(Gravity.CENTER); tvDot.setVisibility(GONE); tvDot.setTextColor(context.getResources().getColor(R.color.color_white)); tvDot.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.circle_dot_red_bg)); final int index = i; prl.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) {// Toast.makeText(context, titles[index], Toast.LENGTH_SHORT).show(); setSelectStyle(index); if(onItemOnclickListener != null) { onItemOnclickListener.onItemClick(index); } } }); cly.addView(textView); prl.addView(cly, rlp); prl.addView(tvDot, rlDot); addView(prl, lp); textViews.add(textView); imageViews.add(imageView); tvDots.add(tvDot); } setSelectStyle(currentIndex); } public void setSelectStyle(int index) { int size = titles.length; for(int i = 0; i < size; i++) { if(i == index) { textViews.get(i).setTextColor(context.getResources().getColor(txtSelectedColor)); imageViews.get(i).setSelected(true); } else { textViews.get(i).setTextColor(context.getResources().getColor(txtColor)); imageViews.get(i).setSelected(false); } } } /** * 设置圆点 * @param index 圆点索引 * @param count 圆点个数 */ public void setDotsCount(int index, int count) { if(tvDots == null || index > tvDots.size() - 1) return; if(count > 0) { tvDots.get(index).setVisibility(VISIBLE); tvDots.get(index).setText(count + ""); } else { tvDots.get(index).setVisibility(GONE); } } public interface OnItemOnclickListener { void onItemClick(int index); } private int sp2px(Context context, float spValue) { final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } private int dip2px(Context context, float dipValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); }}上面就是第二部算法的封装过程(还可以根据特定的需求来扩展),这里给一个最基本的。
最好给出demo下载地址:
GitHub:BottomNavTabs
CSDN: BottomNavTabs
1 0
- Android底部导航布局封装
- Android UI-仿微信底部导航栏布局
- Android UI-仿微信底部导航栏布局
- Android UI-仿微信底部导航栏布局
- 底部导航栏封装
- Android封装好的类似于RadioGroup的底部导航或顶部导航、仿微信底部导航
- Android --中间突出的底部导航栏布局简单实现
- Android手机底部导航栏遮挡住布局问题解决方案
- Android流行UI布局:底部导航(BottomNavigationView+ViewPager+Fragment)
- LinearLayout 布局 底部固定导航
- HorizontalScrollView布局加底部导航
- android底部导航栏
- Android 通用底部导航
- android底部导航栏
- android之底部导航
- android 底部导航总结
- Android底部导航栏
- android 底部导航栏
- Gym 101205 (ACM-ICPC World Finals 2012)
- json解析及解析远
- runFile.py
- HTML5跳伞游戏-看谁先安全降落地面源码下载
- redis 充当web缓存
- Android底部导航布局封装
- 软件工程基础学习笔记--软件生命周期学习
- Lua 元表
- android 权限大全
- eclipse无法使用Ctrl+Shift+F快捷键
- java 反射获得类的属性和父类的属性
- 基于react、redux的todoLists
- 二进制转换与此平台,VMware Workstation不,Workstation 不可恢复,此虚拟环境中的长模式
- JVM运行时数据区