转载请标明出处: http://blog.csdn.net/airsaid/article/details/50836296
本文出自:周游的博客

  • 最终效果
  • 具体实现
    • 1自定义一个类继承ViewGroup
    • 2布局引入自定义View
    • 3使用

最终效果

首先来看看效果图:

其他地方很好实现,就是热门搜索有点麻烦,由于数据的不确定性,那么像GridView明显不能满足了,这时候就只能自己来定义一个布局了。

最终实现后的效果:

具体实现

1,自定义一个类继承ViewGroup

/*** 自定义流布局* @author zhouyou*/
public class ZFlowLayout extends ViewGroup{// 存储所有子Viewprivate List<List<View>> mAllChildViews = new ArrayList<>();// 每一行的高度private List<Integer> mLineHeight = new ArrayList<>();public ZFlowLayout(Context context) {this(context, null);}public ZFlowLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public ZFlowLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// 父控件传进来的宽度和高度以及对应的测量模式int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);int modeWidth = MeasureSpec.getMode(widthMeasureSpec);int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);int modeHeight = MeasureSpec.getMode(heightMeasureSpec);// 如果当前ViewGroup的宽高为wrap_content的情况int width = 0;// 自己测量的 宽度int height = 0;// 自己测量的高度// 记录每一行的宽度和高度int lineWidth = 0;int lineHeight = 0;// 获取子view的个数int childCount = getChildCount();for(int i = 0;i < childCount; i++){View child = getChildAt(i);// 测量子View的宽和高measureChild(child, widthMeasureSpec, heightMeasureSpec);// 得到LayoutParamsMarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();// 子View占据的宽度int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;// 子View占据的高度int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;// 换行时候if(lineWidth + childWidth > sizeWidth){// 对比得到最大的宽度width = Math.max(width, lineWidth);// 重置lineWidthlineWidth = childWidth;// 记录行高height += lineHeight;lineHeight = childHeight;}else{// 不换行情况// 叠加行宽lineWidth += childWidth;// 得到最大行高lineHeight = Math.max(lineHeight, childHeight);}// 处理最后一个子View的情况if(i == childCount -1){width = Math.max(width, lineWidth);height += lineHeight;}}// wrap_contentsetMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width,modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {mAllChildViews.clear();mLineHeight.clear();// 获取当前ViewGroup的宽度int width = getWidth();int lineWidth = 0;int lineHeight = 0;// 记录当前行的viewList<View> lineViews = new ArrayList<View>();int childCount = getChildCount();for(int i = 0;i < childCount; i ++){View child = getChildAt(i);MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();int childWidth = child.getMeasuredWidth();int childHeight = child.getMeasuredHeight();// 如果需要换行if(childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width){// 记录LineHeightmLineHeight.add(lineHeight);// 记录当前行的ViewsmAllChildViews.add(lineViews);// 重置行的宽高lineWidth = 0;lineHeight = childHeight + lp.topMargin + lp.bottomMargin;// 重置view的集合lineViews = new ArrayList();}lineWidth += childWidth + lp.leftMargin + lp.rightMargin;lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);lineViews.add(child);}// 处理最后一行mLineHeight.add(lineHeight);mAllChildViews.add(lineViews);// 设置子View的位置int left = 0;int top = 0;// 获取行数int lineCount = mAllChildViews.size();for(int i = 0; i < lineCount; i ++){// 当前行的views和高度lineViews = mAllChildViews.get(i);lineHeight = mLineHeight.get(i);for(int j = 0; j < lineViews.size(); j ++){View child = lineViews.get(j);// 判断是否显示if(child.getVisibility() == View.GONE){continue;}MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();int cLeft = left + lp.leftMargin;int cTop = top + lp.topMargin;int cRight = cLeft + child.getMeasuredWidth();int cBottom = cTop + child.getMeasuredHeight();// 进行子View进行布局child.layout(cLeft, cTop, cRight, cBottom);left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;}left = 0;top += lineHeight;}}/*** 与当前ViewGroup对应的LayoutParams*/@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {return new MarginLayoutParams(getContext(), attrs);}
}

2,布局引入自定义View

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.hkddy8.flowlabledemo.MainActivity" ><com.hkddy8.flowlabledemo.view.ZFlowLayoutandroid:id="@+id/flowLayout"android:layout_width="match_parent"android:layout_height="wrap_content" />
</RelativeLayout>  

3,使用

public class MainActivity extends Activity {private ZFlowLayout mFlowLayout;private String[] mLabels = {"购物","美食","游玩","北京","CSDN", "Airsaid", "周游", "新春送祝福"};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mFlowLayout = (ZFlowLayout) findViewById(R.id.flowLayout);initLabel();}// 初始化标签private void initLabel() {MarginLayoutParams layoutParams = new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);layoutParams.setMargins(30, 30, 10, 10);// 设置边距for (int i = 0; i < mLabels.length; i++) {final TextView textView = new TextView(MainActivity.this);textView.setTag(i);textView.setTextSize(15);textView.setText(mLabels[i]);textView.setPadding(24, 11, 24, 11);textView.setTextColor(Color.BLACK);textView.setBackgroundResource(R.drawable.lable_item_bg_normal);mFlowLayout.addView(textView, layoutParams);// 标签点击事件textView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(getApplicationContext(), mLabels[(int) textView.getTag()], Toast.LENGTH_SHORT).show();}});}}
}

其中背景的Shape代码:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" ><stroke
        android:width="1dp"android:color="#000000" />
</shape>  

源码下载:http://download.csdn.net/detail/airsaid/9456718

Android 自定义控件之打造流布局实现热门搜索标签相关推荐

  1. Android自定义控件:打造自己的QQ空间主页

    前面已经实现过仿QQ的List抽屉效果以及仿QQ未读消息拖拽效果,具体请见: Android自定义控件:类QQ抽屉效果 Android自定义控件:类QQ未读消息拖拽效果 趁热打铁,这次我们实现QQ空间 ...

  2. php怎么做热门搜索标签,实现phpcms v9全站热门搜索关键词自动调用

    实现此功能其实并不难,虽然官方没有在发布版里做好,但系统自带了关键词模型,只是没有实现,我们修改一下程序来实现. 首先找到 /phpcms/model/keyword_model.class.php ...

  3. android热门搜索标签,Android网易云历史搜索和热门标签

    Android网易云历史搜索和热门标签 最近开发了一个网易云音乐播放器,有这么一个需求,需要展示搜索建议,历史搜索记录 项目地址: github.com/shellhub/Ne- search_ent ...

  4. 【Android自定义控件】仿IOS风格的搜索框

    iOS很多控件的设计都是很值得借鉴的存在,作为移动开发的初学者,我们可以把这种模仿等同于学画.练字时为铸就基础的临摹行为.达者为师,努力学习别人的优点吧.  这里是仿IOS搜索框风格的自定义控件,引用 ...

  5. Android SurfaceView实战 打造抽奖转盘

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41722441 ,本文出自:[张鸿洋的博客] 1.概述 今天给大家带来Surfac ...

  6. GreenDao+SearchView+FlowLoyout实现搜索历史和热门搜索

    之前写过一个静态的搜索页 FlowLayout流式布局实现标签.类似热门搜索这种效果 只是能实现界面效果,但是往往开发中是要把搜索历史缓存到本地数据库中,所以在原基础上添加了数据库功能. 并且把搜索框 ...

  7. Android自定义控件:从零开始实现魅族flyme6应用市场应用详情弹出式layout

    前几天无意中发现魅族flyme6应用市场的应用详情界面非常有意思,作为一枚程序员,看到有意思的东西怎么办?当然是想办法自己也整一个啦,哈哈. 废话不多说,下面先看看魅族flyme6应用市场详情页弹出时 ...

  8. dedecms模板中调用热门搜索关键词的方法

    在很多时候,搜索框下面,需要显示最近的热门搜索,那么dedecms的热门搜索标签是: {dede:hotwords num='3'/} "3"代表的调用条数 通常情况下dedecm ...

  9. Android 自定义控件打造史上最简单的侧滑菜单

    侧滑菜单在很多应用中都会见到,最近QQ5.0侧滑还玩了点花样~~对于侧滑菜单,一般大家都会自定义ViewGroup,然后隐藏菜单栏,当手指滑动时,通过Scroller或者不断的改变leftMargin ...

最新文章

  1. 专访微软全球资深副总裁:中国AI正在爆发式崛起,千万不要复制美国,要建立自己的模式,才能做领导者
  2. ttf能改成gfont吗_中国废弃轮胎,被非洲人买去做成凉鞋!15元一双,至少能穿10年...
  3. 一分钟明确 VS manifest 原理
  4. leetcode538. 把二叉搜索树转换为累加树
  5. ADFLogger的SLF4J绑定–缺少的部分
  6. windows下eclipse搭建android_ndk开发环境
  7. PYTHON学习0011:enumerate()函数的用法----2019-6-8
  8. maven 强制jdk的版本
  9. 谷歌Chrome浏览器如何截图长图
  10. 常见python爬虫框架_python的爬虫框架有哪些
  11. java string 深拷贝_探讨java深拷贝
  12. 计算机弹奏两只老虎爱跳舞,原神风物之诗琴乐谱
  13. 计算机硬盘问题要求备份在弄,硬盘驱动器故障解决方案
  14. 程序人生 - 2020年杭州市积分入学实施办法权威解读
  15. C#将ip地址转换成长整形数字的代码
  16. 这个Kaggle三项排行榜的“顶级大师”,今年17岁
  17. python中pixels函数_Python的PIL库中getpixel方法的使用
  18. python音乐可视化效果_python 音频可视化
  19. maven~本地仓库的指定
  20. SLAM本质剖析-Boost

热门文章

  1. 游戏盒子-账号(小号)交易系统的小结
  2. 博士申请 | 英国华威大学计算机大数据团队招收数据挖掘方向全奖博士生
  3. python将图片裁剪成九宫格
  4. 【贝店】2019-让更多人过上更好生活。
  5. springboot logback 日志配置。
  6. 二胡音准软件 android,二胡音准app软件
  7. 北京君正收购ov和思比科
  8. 物联网碰壁后,这位创业者总结失败五大原因
  9. 玩转新版12306之抢票篇
  10. jquery电商分类导航js特效