Android历史搜索和热门标签

news/2024/11/23 9:53:18/

前言

搜索界面一直是一个APP至关重要的部分,也是用户用的最多的界面,那么历史搜索和热门标签的话,也是这个界面所需要的重要的组成部分。
本篇文章旨在帮助大家如何写好两个重要的部分。话不多说,先上图

界面

这里写图片描述

用到的控件和框架

1.Android ORM框架 GreenDao3.0

2.SearchView在ToolBar中的使用

3.FlowLayoutTag 标签控件(也是本人写的控件,具体在引用如下)

compile’com.daidingkang:flowlayouttag:1.0.0’

FlowLayoutTag主要代码

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());}@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);// wrapContentint 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);// 得到LayoutParamsMarginLayoutParams 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);// 重置lineWidthlineWidth = 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));}// 储存所有的Viewprivate ArrayList<ArrayList<View>> mAllViews = new ArrayList<>();// 储存每一行的高度private ArrayList<Integer> mLineHeight = new ArrayList<>();@Overrideprotected 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<View> 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);// 记录当前行的viewmAllViews.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++) {// 获取当前行的viewlineViews = 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*/@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {// TODO Auto-generated method stubreturn 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() {@Overridepublic 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<String> 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() {@Overridepublic 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() {@Overridepublic 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主要代码

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;@Overridepublic void initView() {setSupportActionBar(toolbar);getSupportActionBar().setDisplayHomeAsUpEnabled(true);initHotTag();historyDao = GreenDaoHelper.getDaoSession().getSearchHistoryDao();
//设置我们的SearchViewinitSearchView();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() {@Overridepublic 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;}@Overridepublic boolean onQueryTextChange(String newText) {return false;}});}/*** 历史搜索*/private void initHistoryTag() {List<SearchHistory> searchHistories = historyDao.loadAll();if (historyDao != null && searchHistories != null && searchHistories.size() != 0) {List<String> historyList = new ArrayList<>();for (SearchHistory searchHistory : searchHistories) {historyList.add(searchHistory.getSearchContent());}lHistory.setVisibility(View.VISIBLE);hisFlowLayout.setListData(historyList);hisFlowLayout.setOnTagClickListener(new FlowLayout.OnTagClickListener() {@Overridepublic 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() {@Overridepublic void TagClick(String text) {MyApplication.toastor.showToast(text);}});}@Overrideprotected int getContentViewLayoutID() {return R.layout.activity_search;}@Overrideprotected void onResume() {super.onResume();initHistoryTag();}@Overridepublic 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() {@Overridepublic void onClick(DialogInterface dialog, int which) {lHistory.setVisibility(View.GONE);hisFlowLayout.cleanTag();historyDao.deleteAll();}});builder.setNegativeButton("取消", null);builder.create().show();break;}}
}

主要布局文件

<?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"><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>

如果有疑问和见解,也欢迎大家在下面留言,我会一一回复大家

以上


http://www.ppmy.cn/news/769862.html

相关文章

盘点7家芯片厂商的无人机布局

颠覆者&#xff0c;在上游&#xff0c;越是处于上游&#xff0c;就越是紧扼整条产业链的命脉&#xff0c;无人机市场也不例外。 上游芯片厂商正在逐渐往下游去渗透&#xff0c;相比起从下往上走&#xff0c;它们具有天然的优势。 此篇文章盘点了7家厂商在无人机领域的布局&…

【长文慎入】百度阿里网易大疆等大小厂前端校招面筋

关注“重度前端” 助力前端深度学习 ━━━━ 自我介绍下&#xff1a;某985硕士&#xff0c;程序媛&#xff0c;接触前端一年时间。从八月份开始校招面试笔试&#xff0c;前前后后大厂小厂也都面了挺多&#xff0c;不过大厂基本都被我挂完了&#xff0c;哭晕我&#xff0c;还是…

Web APls-day04

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 日期对象 日期对象&#xff1a;用来表示时间的对象 作用&#xff1a;可以得到当前系统时间 实例化 在代码中发现…

大疆产品上岸经验分享

笔试: 1、英文的20个词的自我介绍,和描述一个团队发生的分歧,并且描述怎么解决的; 2、写3个科技热点事件,然后选取一个从,事件本身,影响力,传播方式等来描述 3、请谈谈对《三个和尚没水吃》的理解 4、谈一谈为什么要加入大疆创新,并谈谈你想做大疆的哪个项目,假如你是…

【LeetCode周赛】2022上半年题目精选集——贪心

文章目录 2136. 全部开花的最早一天&#xff08;贪心&#xff09;⭐⭐⭐⭐⭐思路代码语法解析&#xff1a;Integer[] id IntStream.range(0, plantTime.length).boxed().toArray(Integer[]::new); 2141. 同时运行 N 台电脑的最长时间&#xff08;贪心&#xff09;⭐⭐⭐⭐⭐解…

Shamir秘密共享

目录 Shamir秘密共享 秘密共享的概念 问题1: 问题2: 秘密分割门限方案的定义 Shamir秘密共享方案 组成 构造思路 构造 计算f(x) 例1 例2 二、GMW方案 Shamir秘密共享 秘密共享的概念 问题1: 保险柜中存放有10个人的共有财产&#xff0c;要从保险柜中取出物品&am…

509实验室打印机双面打印的方法

1.首先IP地址为&#xff1a;10.20.105.145 方法1&#xff1a; 1.用wps有个双面打印&#xff0c;然后打印完需要把打印完单面的纸给纵向翻转&#xff0c;让有字体的那一面朝上&#xff0c;并且字的朝向为右&#xff0c;最后一步就是把这些纸的最上面的挪到最下面&#xff0c;依…

想请问下PDF双面打印时(打印机自动双面打印)为什么反面那页的内容是倒过来的,应该怎么设置?...

用foxit reader 打印pdf 直接设置为双面打印并且一张2页打印&#xff0c;发现正反面刚好倒着来的&#xff0c;其实说的正反面倒着是从左右翻的角度来讲的&#xff0c;如果上下翻会发现刚好是这个顺序的&#xff0c;这个是要在双面打印设置里头去设置那个长边和短边的方向。在fo…