搜索界面一直是一个APP至关重要的部分,也是用户用的最多的界面,那么历史搜索和热门标签的话,也是这个界面所需要的重要的组成部分。
本篇文章旨在帮助大家如何写好两个重要的部分。话不多说,先上图
1.Android ORM框架 GreenDao3.0
2.SearchView在ToolBar中的使用
3.FlowLayoutTag 标签控件(也是本人写的控件,具体在引用如下)
compile’com.daidingkang:flowlayouttag:1.0.0’
FlowLayout.class
/**
* 自定义流式布局
*/
public class FlowLayout extends ViewGroup {
private LayoutInflater mInflater;
private boolean isColorful;
public FlowLayout(Context context) {
this(context, null);
}
public FlowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mInflater = LayoutInflater.from(getContext());
}
@Override
protected 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);
// wrapContent
int width = 0;
int height = 0;
// 记录每一行的宽和高
int lineWidth = 0;
int lineHeight = 0;
// 得到内部元素的个数
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
// 测量子View的宽和高
measureChild(child, widthMeasureSpec, heightMeasureSpec);
// 得到LayoutParams
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
// 子view的占据的宽度
int childWidth = child.getMeasuredWidth() + lp.leftMargin
+ lp.rightMargin;
// 子view占据的高度
int childHeight = child.getMeasuredHeight() + lp.topMargin
+ lp.bottomMargin;
// 换行
if (lineWidth + childWidth > sizeWidth - getPaddingLeft()
- getPaddingRight()) {
// 对比得到最大的宽度
width = Math.max(width, lineWidth);
// 重置lineWidth
lineWidth = childWidth;
// 记录行高
height += lineHeight;
lineHeight = childHeight;
} else {
// 未换行
// 叠加行宽
lineWidth += childWidth;
// 得到当前最大高度
lineHeight = Math.max(lineHeight, childHeight);
}
// 最后一个控件
if (i == count - 1) {
width = Math.max(lineWidth, width);
height += lineHeight;
}
}
// Log.i("test", "sizeWidth" + sizeWidth);
// Log.i("test", "sizeHeight" + sizeHeight);
setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth
: width + getPaddingLeft() + getPaddingRight(),
modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height
+ getPaddingTop() + getPaddingBottom());
setPadding(dp2px(20), dp2px(10), dp2px(20), dp2px(10));
}
// 储存所有的View
private ArrayList> mAllViews = new ArrayList<>();
// 储存每一行的高度
private ArrayList mLineHeight = new ArrayList<>();
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
// 清除一下list集合
mAllViews.clear();
mLineHeight.clear();
// 得到viewGroup当前宽度
int width = getWidth();
int lineWidth = 0;
int lineHeight = 0;
ArrayList lineViews = new ArrayList<>();
int count = getChildCount();
for (int i = 0; i < count; 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
- getPaddingLeft() - getPaddingRight()) {
// 记录当前行高
mLineHeight.add(lineHeight);
// 记录当前行的view
mAllViews.add(lineViews);
// 重置行宽和行高
lineWidth = 0;
lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
// 重置lineViews集合
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);
// 设置子view的位置
int left = getPaddingLeft();
int top = getPaddingTop();
// 有多少行
int lineNum = mLineHeight.size();
for (int i = 0; i < lineNum; i++) {
// 获取当前行的view
lineViews = mAllViews.get(i);
// 当前行高
lineHeight = mLineHeight.get(i);
int lineViewSize = lineViews.size();
for (int j = 0; j < lineViewSize; j++) {
View child = lineViews.get(j);
// 判断子view的状态
if (child.getVisibility() == View.GONE) {
continue;
}
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
int lc = left + lp.leftMargin;
int tc = top + lp.topMargin;
int rc = lc + childWidth;
int bc = tc + childHeight;
// 为子view布局
child.layout(lc, tc, rc, bc);
// 同一行view坐起点坐标的变换
left += childWidth + lp.leftMargin + lp.rightMargin;
}
// 换行时将left重置
left = getPaddingLeft();
// top要加上上一行的行高
top += lineHeight;
}
}
/**
* 默认返回的LayoutParams
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
// TODO Auto-generated method stub
return new MarginLayoutParams(getContext(), attrs);
}
/**
* 设置数据
*/
public void setData(String[] strings) {
int count = strings.length;
for (int i = 0; i < count; i++) {
final TextView tv = (TextView) mInflater.inflate(R.layout.flowlayout_textview, this,
false);
tv.setText(strings[i]);
tv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onTagClickListener != null)
onTagClickListener.TagClick(tv.getText().toString());
}
});
if(isColorful){
Random random = new Random();
int ranColor = 0xff000000 | random.nextInt(0x00ffffff);
tv.setBackgroundColor(ranColor);
}
this.addView(tv);
}
}
/**
* 设置数据
*/
public void setListData(List list) {
int count = list.size();
for (int i = 0; i < count; i++) {
final TextView tv = (TextView) mInflater.inflate(R.layout.flowlayout_textview, this,
false);
tv.setText(list.get(i));
tv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onTagClickListener != null)
onTagClickListener.TagClick(tv.getText().toString());
}
});
this.addView(tv);
}
}
/**
* 添加标签
*
* @param text
*/
public void addTag(String text) {
final TextView tv = (TextView) mInflater.inflate(R.layout.flowlayout_textview, this,
false);
tv.setText(text);
tv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onTagClickListener != null)
onTagClickListener.TagClick(tv.getText().toString());
}
});
if(isColorful){
Random random = new Random();
int ranColor = 0xff000000 | random.nextInt(0x00ffffff);
tv.setBackgroundColor(ranColor);
}
this.addView(tv);
}
/**
* 设置多彩颜色
* @param isColorful
*/
public void setColorful(boolean isColorful) {
this.isColorful = isColorful;
}
/**
* 删除所有标签
*/
public void cleanTag() {
this.removeAllViews();
}
public int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
private OnTagClickListener onTagClickListener;
public void setOnTagClickListener(OnTagClickListener onTagClickListener) {
this.onTagClickListener = onTagClickListener;
}
public interface OnTagClickListener {
void TagClick(String text);
}
}
SearchActivity.class
public class SearchActivity extends BaseActivity implements View.OnClickListener {
@BindView(R.id.searchView)
SearchView searchView;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.hot_flowLayout)
FlowLayout hotFlowLayout;
@BindView(R.id.his_flowLayout)
FlowLayout hisFlowLayout;
@BindView(R.id.ll_history)
LinearLayout lHistory;
@BindView(R.id.delete)
ImageView delete;
SearchHistoryDao historyDao;
@Override
public void initView() {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
initHotTag();
historyDao = GreenDaoHelper.getDaoSession().getSearchHistoryDao();
//设置我们的SearchView
initSearchView();
delete.setOnClickListener(this);
}
private void initSearchView() {
searchView.setIconifiedByDefault(true);//设置展开后图标的样式,这里只有两种,一种图标在搜索框外,一种在搜索框内
searchView.onActionViewExpanded();// 写上此句后searchView初始是可以点击输入的状态,如果不写,那么就需要点击下放大镜,才能出现输入框,也就是设置为ToolBar的ActionView,默认展开
// searchView.requestFocus();//输入焦点
searchView.setSubmitButtonEnabled(true);//添加提交按钮,监听在OnQueryTextListener的onQueryTextSubmit响应
// searchView.setFocusable(true);//将控件设置成可获取焦点状态,默认是无法获取焦点的,只有设置成true,才能获取控件的点击事件
searchView.setIconified(false);//输入框内icon不显示
// searchView.requestFocusFromTouch();//模拟焦点点击事件
searchView.setFocusable(false);
searchView.clearFocus();
// mSearchView.setIconifiedByDefault(true);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
SnackbarUtil.show(toolbar, query);
//插入之前先查询,如果有相同的就不在插入进去
SearchHistory unique = historyDao.queryBuilder().where(SearchHistoryDao.Properties.SearchContent.eq(query)).unique();
if (unique == null) {
historyDao.insert(new SearchHistory(null, query));
}
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
}
/**
* 历史搜索
*/
private void initHistoryTag() {
List searchHistories = historyDao.loadAll();
if (historyDao != null && searchHistories != null && searchHistories.size() != 0) {
List historyList = new ArrayList<>();
for (SearchHistory searchHistory : searchHistories) {
historyList.add(searchHistory.getSearchContent());
}
lHistory.setVisibility(View.VISIBLE);
hisFlowLayout.setListData(historyList);
hisFlowLayout.setOnTagClickListener(new FlowLayout.OnTagClickListener() {
@Override
public void TagClick(String text) {
MyApplication.toastor.showToast(text);
}
});
}
}
/**
* 热门搜索
*/
private void initHotTag() {
String[] mStrings = {"apple", "百度CEO", "阿里巴巴", "绩效股", "中国股市", "美团", "google", "淘宝", "雷军 小米公司", "大疆无人机"};
hotFlowLayout.setColorful(true);
hotFlowLayout.setData(mStrings);
hotFlowLayout.setOnTagClickListener(new FlowLayout.OnTagClickListener() {
@Override
public void TagClick(String text) {
MyApplication.toastor.showToast(text);
}
});
}
@Override
protected int getContentViewLayoutID() {
return R.layout.activity_search;
}
@Override
protected void onResume() {
super.onResume();
initHistoryTag();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.delete:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("确定要删除全部历史记录?");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
lHistory.setVisibility(View.GONE);
hisFlowLayout.cleanTag();
historyDao.deleteAll();
}
});
builder.setNegativeButton("取消", null);
builder.create().show();
break;
}
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:visibility="gone"
android:id="@+id/ll_history"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
>
<TextView
android:id="@+id/his_vertical_bar"
android:layout_width="3dp"
android:layout_height="20dp"
android:background="?attr/colorPrimary"
android:layout_marginRight="4dp"
/>
<TextView
android:layout_toRightOf="@+id/his_vertical_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:gravity="left"
android:text="历史搜索"
android:textColor="@color/font"
android:textSize="15sp"
/>
<ImageView
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="15dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@mipmap/ic_delete"
/>
RelativeLayout>
<com.pulamsi.photomanager.widght.fitsystemwindowlayout.FlowLayout
android:id="@+id/his_flowLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
>
<TextView
android:id="@+id/hot_vertical_bar"
android:layout_width="3dp"
android:layout_height="20dp"
android:background="?attr/colorPrimary"
android:layout_marginRight="4dp"
/>
<TextView
android:layout_toRightOf="@+id/hot_vertical_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:gravity="left"
android:text="热门搜索"
android:textColor="@color/font"
android:textSize="15sp"
/>
RelativeLayout>
<com.pulamsi.photomanager.widght.fitsystemwindowlayout.FlowLayout
android:id="@+id/hot_flowLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
LinearLayout>
LinearLayout>
如果有疑问和见解,也欢迎大家在下面留言,我会一一回复大家
以上