Android历史搜索和热门标签

前言

搜索界面一直是一个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());
    }

    @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主要代码

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>

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

以上

你可能感兴趣的:(Android历史搜索和热门标签)