1. 程式人生 > >仿ios,網易,京東的搜尋介面和功能

仿ios,網易,京東的搜尋介面和功能

由於最新專案需要實現一個搜尋功能,需求是和ios的樣式相同,ios有第三方庫直接引用就可以使用,而android這邊全是md風格的,並不是我想要的,所以只能自己寫了,如果有時間一定封裝成庫。首先看下效果圖
這裡寫圖片描述

 首先看下需要用到的東西,1,首頁搜尋是一個TextView自不必說,主要是熱門搜尋的流式佈局,但是今天的主角不是它,如果不太懂的朋友可以移步這裡:[Android中常見的流式佈局的使用 ](http://blog.csdn.net/sinat_36668731/article/details/53198172),2.就是歷史搜尋,這裡需要用到資料庫的一些知識,我會在後面具體說明。首先看下xml程式碼,非常的簡單:
  <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout android:layout_width="match_parent" android:layout_height="92px" android:gravity="center_vertical" android:focusable="true" android:padding="6px" android:background
="@color/colorTextGroupBg" android:focusableInTouchMode="true" android:orientation="horizontal">
<EditText android:id="@+id/et_search" android:layout_width="0dp" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:layout_margin="6px" android:layout_weight="1" android:background="@drawable/edit_text_bg" android:focusable="false" android:focusableInTouchMode="false" android:hint=" 請輸入要搜尋的關鍵詞" android:paddingBottom="10px" android:paddingLeft="30px" android:paddingTop="10px" android:textColor="#333" android:textColorHint="#666" android:textSize="12sp" /> <TextView android:id="@+id/tv_search" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginRight="20px" android:layout_marginLeft="16px" android:gravity="center" android:text="搜尋" android:textColor="#fff" android:textSize="14sp" android:visibility="gone" /> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="熱門搜尋" android:padding="20px" android:textSize="36px"/> <com.example.jmf.xsearch.flowlayout.FlowLayout android:id="@+id/flow_hot_search" android:layout_width="match_parent" android:layout_height="wrap_content"> </com.example.jmf.xsearch.flowlayout.FlowLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="20px"> <TextView android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="歷史搜尋" android:textSize="36px"/> <ImageView android:id="@+id/iv_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/iv_delete"/> </LinearLayout> <com.example.jmf.xsearch.MyListView android:id="@+id/lv_search" android:layout_width="match_parent" android:layout_height="match_parent"> </com.example.jmf.xsearch.MyListView> </LinearLayout> </ScrollView>

相信大家一看就能明白,這裡順便解決了ScrollView巢狀ListView只顯示一行的問題。廢話不多說了,咱們直接看下activity中的程式碼

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        //初始化監聽
        initListener();
        //初始化資料
        initData();
    }

onCreate()方法中只有兩個方法,這裡是不是很清楚,不是?好吧,咱們接著下一個環節,看下initListener()中都有什麼

private void initListener() {
        //搜尋框的觸控事件的監聽
        etSearch.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                //點選輸入框顯示搜尋並獲取焦點
                etSearch.setFocusable(true);
                etSearch.setFocusableInTouchMode(true);
                tvSearch.setVisibility(View.VISIBLE);
                return false;
            }

        });

        tvSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 按完搜尋鍵後將當前查詢的關鍵字儲存起來,如果該關鍵字已經存在就不執行儲存
                boolean hasData = hasData(etSearch.getText().toString().trim());
                if (!hasData) {
                    insertData(etSearch.getText().toString().trim());

                    queryData("");
                }

                etSearch.setFocusable(false);
                etSearch.setFocusableInTouchMode(false);
                etSearch.clearFocus();
                tvSearch.setVisibility(View.GONE);

                //跳轉到H5介面
                String searchContent = etSearch.getText().toString().trim();
                Toast.makeText(MainActivity.this, "搜尋內容為:"+searchContent, Toast.LENGTH_SHORT).show();
                etSearch.setText("");
            }
        });

        //"清空搜尋歷史"按鈕
        ivDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //清空資料庫
                deleteData();
                queryData("");
            }
        });
    }

好了,最主要的來了,就是initdata()方法中執行的邏輯,接下來可是一連串的程式碼哦

protected void initData() {
        //插入資料
        initSearch();

        //例項化資料庫SQLiteOpenHelper子類物件
        helper = new RecordSQLiteOpenHelper(this);
        // 第一次進入時查詢所有的歷史記錄
        queryData("");
    }
    /*插入資料*/
    private void insertData(String tempName) {
        db = helper.getWritableDatabase();
        db.execSQL("insert into records(name) values('" + tempName + "')");
        db.close();
    }
    /*檢查資料庫中是否已經有該條記錄*/
    private boolean hasData(String tempName) {
        //從Record這個表裡找到name=tempName的id
        Cursor cursor = helper.getReadableDatabase().rawQuery(
                "select id as _id,name from records where name =?", new String[]{tempName});
        //判斷是否有下一個
        return cursor.moveToNext();
    }

    /*模糊查詢資料 並顯示在ListView列表上*/
    private void queryData(String tempName) {

        //模糊搜尋
        Cursor cursor = helper.getReadableDatabase().rawQuery(
                "select id as _id,name from records where name like '%" + tempName + "%' order by id desc ", null);
        // 建立adapter介面卡物件,裝入模糊搜尋的結果
        adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, new String[]{"name"},
                new int[]{android.R.id.text1}, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        // 設定介面卡
        lvSearch.setAdapter(adapter);
        adapter.notifyDataSetChanged();
        //歷史記錄的點選事件
        lvSearch.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                //跳轉到H5介面
                //獲取到使用者點選列表裡的文字,並自動填充到搜尋框內
                TextView textView = (TextView) view.findViewById(android.R.id.text1);
                String searchContent = textView.getText().toString();
                Toast.makeText(MainActivity.this, ""+searchContent, Toast.LENGTH_SHORT).show();
                etSearch.setText("");
            }
        });
    }

    /**
     *清空資料
     */
    private void deleteData() {
        db = helper.getWritableDatabase();
        db.execSQL("delete from records");
        db.close();
    }
    //初始化熱門搜尋
    private void initSearch() {
        for (int i = 0; i < datas.length; i++) {
            final TextView textView = new TextView(this);
            textView.setText(datas[i]);
//            textView.setTextSize(DensityUtil.dip2px(this, 5));
            //提供邊距的物件,並設定到textView中
            ViewGroup.MarginLayoutParams mp = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            mp.leftMargin = DensityUtil.dip2px(this, 5);
            mp.rightMargin = DensityUtil.dip2px(this, 5);
            mp.topMargin = DensityUtil.dip2px(this, 5);
            mp.bottomMargin = DensityUtil.dip2px(this, 5);
            textView.setLayoutParams(mp);

            //設定背景
            //方式二:
            //儲存按下能顯示selector的效果,需要設定一個如下的屬性
            textView.setBackground(DrawUtils.getSelector(DrawUtils.getDrawable(MainActivity.this,Color.rgb(210, 210, 210), DensityUtil.dip2px(this, 4)), DrawUtils.getDrawable(MainActivity.this,Color.WHITE, DensityUtil.dip2px(this, 4))));

            //新增點選事件,也是實現顯示selector的效果的一種方式
            textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //跳轉到H5介面
                    String searchContent = textView.getText().toString();
                    Toast.makeText(MainActivity.this, ""+searchContent, Toast.LENGTH_SHORT).show();
                    etSearch.setText("");
                }
            });

            //設定邊距
            //設定內邊距
            int padding = DensityUtil.dip2px(this, 10);
            textView.setPadding(padding, padding, padding, padding);

            // 2.新增到FlowLayout佈局中
            flowHotSearch.addView(textView);
        }
    }

到這裡程式碼已經全部擼完了,其中用到了一個SQLiteOpenHelper的實現類,我也一併粘出來

/**
 * Created by jmf on 16/11/15.
 */
//SQLiteOpenHelper子類用於開啟資料庫並進行對使用者搜尋歷史記錄進行增刪減除的操作
public class RecordSQLiteOpenHelper extends SQLiteOpenHelper {

    private static String name = "temp.db";
    private static Integer version = 1;

    public RecordSQLiteOpenHelper(Context context) {
        super(context, name, null, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //開啟資料庫,建立了一個叫records的表,裡面只有一列name來儲存歷史記錄:
        db.execSQL("create table records(id integer primary key autoincrement,name varchar(200))");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

好了,到這裡程式碼已經碼完了,裡面的資料庫只涉及簡單的CRUD功能,不懂也沒關係,可以直接拿走。由於篇幅關係今天就到這裡。還希望大家多多支援