仿b站发现界面关键字的FlowLayout.
来源:互联网 发布:淘宝客户关系管理打折 编辑:程序博客网 时间:2024/05/16 12:52
这段时间想做个仿b站的程序,现在完成了整个界面。一点一点分享出来。
文章开头,感谢鸿洋大神的轮子。(http://blog.csdn.net/lmj623565791/article/details/38352503)
在此基础上改动了一些,觉得更易懂。
1.FlowLayout
这里只贴了onMeasure()和onLayout()方法。具体可以去看鸿洋大神的。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 获得它的父容器为它设置的测量模式和大小 int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); int modeHeight = MeasureSpec.getMode(heightMeasureSpec); // 如果是warp_content情况下,记录宽和高 int width = 0; int height = 0; /** * 记录每一行的宽度,width不断取最大宽度 */ int lineWidth = 0; /** * 每一行的高度,累加至height */ int lineHeight = 0; int cCount = getChildCount(); //遍历 for (int i = 0; i < cCount; i++) { View child = getChildAt(i); // 测量每一个child的宽和高 measureChild(child, widthMeasureSpec, heightMeasureSpec); // 得到child的lp MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); // 当前子空间实际占据的宽度 int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; // 当前子空间实际占据的高度 int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; /** * 如果加入当前child,则超出最大宽度,则的到目前最大宽度给width,类加height 然后开启新行 */ if (lineWidth + childWidth > sizeWidth) { width = Math.max(lineWidth, childWidth); lineWidth = childWidth;// 重新开启新行,开始记录 // 叠加当前高度 height += lineHeight; // 开启记录下一行的高度 lineHeight = childHeight; } else {// 否则累加值lineWidth,lineHeight取最大高度 lineWidth += childWidth; lineHeight = Math.max(lineHeight, childHeight); }// 如果是最后一个,则将当前记录的最大宽度和当前lineWidth做比较 if (i == cCount - 1) { width = Math.max(width, lineWidth); height += lineHeight; } } setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth : width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight : height); } /** * 存储所有的View,按行记录 */ private List<List<View>> mAllViews = new ArrayList<List<View>>(); /** * 记录每一行的最大高度 */ private List<Integer> mLineHeight = new ArrayList<Integer>(); @Override protected void **onLayout**(boolean changed, int l, int t, int r, int b) { mAllViews.clear(); mLineHeight.clear(); int width=getWidth(); int lineWidth = 0; int lineHeight = 0; // 存储每一行所有的childView List<View> lineViews = new ArrayList<View>(); int cCount = getChildCount(); // 遍历 for (int i=0;i<cCount;i++){ View child=getChildAt(i); MarginLayoutParams lp = (MarginLayoutParams) child .getLayoutParams(); int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); // 如果已经需要换行 if (childWidth+lp.leftMargin+lp.rightMargin+lineWidth > width){ // 记录这一行所有的View以及最大高度 mLineHeight.add(lineHeight); // 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView mAllViews.add(lineViews); lineWidth=0; lineViews =new ArrayList<>(); } /** * 如果不需要换行,则累加 */ lineWidth+=childWidth+lp.leftMargin+lp.rightMargin; lineHeight=Math.max(lineHeight,childHeight+lp.topMargin+lp.bottomMargin); lineViews.add(child); } // 记录最后一行 mLineHeight.add(lineHeight); mAllViews.add(lineViews); int left = 0; int top = 0; // 得到总行数 int lineNums = mAllViews.size(); for (int i=0;i<lineNums;i++){ // 每一行的所有的views lineViews=mAllViews.get(i); lineHeight=mLineHeight.get(i); // 遍历当前行所有的View for (int j=0;j<lineViews.size();j++){ View child = lineViews.get(j); if (child.getVisibility() == View.GONE) { continue; } MarginLayoutParams lp = (MarginLayoutParams) child .getLayoutParams(); //计算childView的left,top,right,bottom int lc = left + lp.leftMargin; int tc = top + lp.topMargin; int rc =lc + child.getMeasuredWidth(); int bc = tc + child.getMeasuredHeight(); child.layout(lc, tc, rc, bc); left += child.getMeasuredWidth() + lp.rightMargin + lp.leftMargin; } left = 0; top += lineHeight; }
自定义ViewGroup。
思路就是先测量父容器的大小和关键字的大小。再按宽度一个一个放进去。
2.引用
在主布局中引用这个类。
<com.example.ly.myapplication.view.FlowLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/roottext" android:layout_margin="5dp"> </com.example.ly.myapplication.view.FlowLayout>
这里需要动态生成textview,而不是一个一个写在xml文件里面。可以动态化控件
//list里放后台传过来的关键字数据 有多少数据可以创建多少roottext = (FlowLayout) find.findViewById(R.id.roottext); for (int i=0;i<list.size();i++){ TextView tv=new TextView(this); tv.setText(list.get(i)); tv.setBackgroundResource(R.drawable.flowlayout_text); tv.setTextColor(getResources().getColor(R.color.black_font)); LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); lp.setMargins(5,5,5,5); tv.setLayoutParams(lp); roottext.addView(tv); }
在drawable里写textview的样式。(AS里drawable放自定义样式,mipmap放图片)
<shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="@color/white"/> <stroke android:width="1dp" android:color="@color/gray" /> <corners android:radius="2dp"/> <padding android:bottom="2dp" android:left="10dp" android:right="10dp" android:top="2dp" /></shape>
结果图:
1 0
- 仿b站发现界面关键字的FlowLayout.
- 微信中 - 发现 - 界面的实现
- java界面,BorderLayout,GridLayout,FlowLayout
- 仿qq界面的实现
- 仿QQ界面的切换
- 类似于文档流的界面布局器:改进版的FlowLayout
- swing 类似于文档流的界面布局器:改进版的FlowLayout
- java面板的使用与五种界面布局方式(FLowLayout、BorderLayout、GridLayout、CardLayout、BoxLayout)
- FlowLayout的使用
- FlowLayout遇到的坑
- FlowLayout的使用
- 发现一个很牛B的问题
- 超强仿DOS界面的网站
- 关于仿ubuntu的IOS界面
- 仿网易、人人滑动界面的实现
- 仿MAC界面的ubuntu系统
- android仿QQ的UI界面
- 基于JAVA的界面开发:仿QQ
- 欢迎使用CSDN-markdown编辑器
- 【VIP】342. Power of Four 【E】【leetcode】
- ScrollView里嵌套ListView(或者gridview)时,内部控件滑动时外部控件也会动的异常处理
- 解决 Toolbar 的 Menu 图标无法显示的问题
- Android 换肤功能实现
- 仿b站发现界面关键字的FlowLayout.
- ubuntu下直接连接远程服务器,并传输文件
- MySQL触发器中通过SELECT语句给变量赋值
- Telephony Call
- 【网虫】使用国外 DNS 造成国内网站访问慢的解决方法
- foundation常用类笔记
- 数据库之mac下完全卸载mysql
- WebView详解 typename 记录点滴
- Java内存泄露