流式布局SearchFlowLayout
来源:互联网 发布:淘宝开店货从哪里来 编辑:程序博客网 时间:2024/06/06 03:54
看到搜索框下面一般都有最近的搜索记录,这些搜索记录一般是流式布局,下面的是一个流式布局,一个继承ViewGroup的自定义view,其中一种使用场景就是在搜索框下面,效果图如下:
下面是SearchFlowLayout的源码:
public class SearchFlowLayout extends ViewGroup { List<Line> lines = new ArrayList<Line>();//所有的行 private Line currentLine; public SearchFlowLayout(Context context) { super(context); } public SearchFlowLayout(Context context, AttributeSet attrs) { super(context, attrs); } public SearchFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } private OnItemClickListener mListener; public void setOnItemClickListener(OnItemClickListener listener) { this.mListener = listener; } public interface OnItemClickListener { void click(int position); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { lines.clear(); currentLine = null; int width = MeasureSpec.getSize(widthMeasureSpec); float maxWidth = width - getPaddingLeft() - getPaddingRight(); float horizontalDistance = dp2px(getContext(), 10); float vercitalDistance = dp2px(getContext(), 10); int childCount = getChildCount(); currentLine = new Line(maxWidth, horizontalDistance, vercitalDistance); lines.add(currentLine); for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); final int position = i; childView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mListener != null) { mListener.click(position); } } }); measureChild(childView, widthMeasureSpec, heightMeasureSpec); if (currentLine.canAddView(childView)) { currentLine.addView(childView); } else { currentLine = new Line(maxWidth, horizontalDistance, vercitalDistance); if (currentLine.canAddView(childView)) { currentLine.addView(childView); } lines.add(currentLine); } } int hight = 0; for (int i = 0; i < lines.size(); i++) { if (i == 0) { hight += getPaddingTop(); } else if (i == lines.size() - 1) { hight += getPaddingBottom(); } hight += lines.get(i).mLineHight + vercitalDistance; } setMeasuredDimension(width, hight); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int lineTop = getPaddingTop(); for (int i = 0; i < lines.size(); i++) { Line line = lines.get(i); line.layout(lineTop); lineTop += line.mLineHight + line.mVercitalDistance; } } /** * 每一行 */ class Line { public List<View> mViews = new ArrayList<View>(); public float mHorizontalDistance;//行中两个子View之间水平间距 public float mVercitalDistance;//两个行竖直间距 public float mMaxWidth;//行中的最大的宽度 public float mUseWidth;//行中已经使用的宽度 public float mLineHight;//行的高度 public Line(float maxWidth, float horizontalDistance, float vercitalDistance) { this.mMaxWidth = maxWidth; this.mHorizontalDistance = horizontalDistance; this.mVercitalDistance = vercitalDistance; } /** * 是否能添加View * * @param view * @return */ private boolean canAddView(View view) { if (mViews.size() == 0) { mUseWidth += getPaddingLeft() + getPaddingRight() + view.getMeasuredWidth(); return true; } else { mUseWidth += view.getMeasuredWidth() + mHorizontalDistance; } if (mUseWidth <= mMaxWidth) { return true; } return false; } /** * 添加View * * @param view */ private void addView(View view) { mViews.add(view); mLineHight = mLineHight < view.getMeasuredHeight() ? view.getMeasuredHeight() : mLineHight; } /** * 摆放子view */ private void layout(int lineTop) { int left = getPaddingLeft(); int top = lineTop; int right = 0; int bottom = 0; for (int i = 0; i < mViews.size(); i++) { View view = mViews.get(i); right = left + view.getMeasuredWidth(); bottom = top + view.getMeasuredHeight(); view.layout(left, top, right, bottom); left += view.getMeasuredWidth() + mHorizontalDistance; } } } /** * dp转px * * @param context * @param dp * @return */ public int dp2px(Context context, float dp) { float density = context.getResources().getDisplayMetrics().density; int px = (int) (dp * density + 0.5f); return px; }}
使用:
xml布局:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="10dp" android:paddingBottom="10dp" android:background="#E6E6E6"> <LinearLayout android:layout_width="match_parent" android:layout_height="45dp" android:orientation="horizontal" android:background="@drawable/search_bg" android:layout_marginLeft="10dp" android:layout_marginRight="10dp"> <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="10dp" android:layout_gravity="center_vertical" android:background="@drawable/search1"/> <EditText android:layout_width="match_parent" android:layout_height="match_parent" android:background="@null" /> </LinearLayout> </FrameLayout> <com.org.sleepgod.widget.SearchFlowLayout android:id="@+id/fl_view" android:padding="10dp" android:layout_width="match_parent" android:layout_height="wrap_content"> </com.org.sleepgod.widget.SearchFlowLayout></LinearLayout>
java代码:
public class FlowLayoutActivity extends Activity { private SearchFlowLayout mSearchFlowLayout; private String[] mNames = new String[]{"大主宰","龙王传说","一念永恒","雪鹰领主","帝霸","最强狂兵","美食供应商","我是大明星","全职法师","我的贴身校花","重生完美时代" ,"318女生宿舍"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_flowlayout); mSearchFlowLayout = (SearchFlowLayout) findViewById(R.id.fl_view); for (int i = 0; i < mNames.length; i++) { TextView textView = new TextView(this); textView.setText(mNames[i]); textView.setBackgroundResource(R.drawable.text_bg); GradientDrawable gradientDrawable = (GradientDrawable) textView.getBackground(); gradientDrawable.setStroke(1, UIUtils.randomColor()); mSearchFlowLayout.addView(textView); } mSearchFlowLayout.setOnItemClickListener(new SearchFlowLayout.OnItemClickListener() { @Override public void click(int position) { Toast.makeText(FlowLayoutActivity.this,mNames[position],Toast.LENGTH_SHORT).show(); } }); }}
text_bg
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#FFFFFF" /> <stroke android:width="1dp" android:color="#61e0fe" /> <padding android:bottom="6dp" android:left="10dp" android:right="10dp" android:top="6dp" /> <corners android:radius="25dp" /></shape>
search_bg
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="25dp"/> <solid android:color="#FFF"/> <stroke android:color="#7A7A7A"></stroke></shape>
源码链接:https://github.com/sleepgodMaster/sleepgod-master/blob/master/src/main/java/com/org/sleepgod/widget/SearchFlowLayout.java
0 0
- 流式布局SearchFlowLayout
- GUI布局:边界布局、流式布局、网格布局、卡片布局
- Java_流式布局、边框布局以及网格布局
- 流式布局、浮动布局及绝对定位布局
- 流式布局,标签式布局
- Java_GUI_布局_流式布局
- 网站布局中的瀑布流式布局
- 固定布局与流式布局
- 练习---流式布局和网格布局
- java布局——流式布局
- 自定义布局VerticalView(倒置流式布局)
- css sticky footer布局+流式布局
- 流式布局
- html流式布局
- 拥抱流式布局
- 流式布局 RadioGroup
- 流式布局
- FlowLayout流式布局
- 配置ssh/config
- JavaScript(ES6)新特性学习汇
- (转载)正向代理与反向代理的区别
- django项目cookies和session的常用操作
- SVN的安装和启动
- 流式布局SearchFlowLayout
- 贪心算法学习
- 杭电oj1869 六度分离(folyd)
- 205. Isomorphic Strings
- MongoDB中聚合(aggregate)的使用
- Mushroom的区间 题解
- jq-选择器
- Android7.0 Rild工作流程
- Python的学习笔记DAY12---python和Mysql之二