京東的熱搜(搜尋)介面(GreenDao,EventBus,Butterknife)
1.先配置GreenDao,Butterknife和EventBus
1.在model的build中加入依賴
//greendao compile 'org.greenrobot:greendao:3.1.0' compile 'org.greenrobot:greendao-generator:3.0.0' //butterknife 黃油刀 compile 'com.jakewharton:butterknife:8.5.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1' //EventBus compile 'org.greenrobot:eventbus:3.0.0'
**2.到這裡EventBus已經配置完成,接著就是GreenDao和Butterknife了:
在model的build中新增:**
apply plugin: 'com.jakewharton.butterknife'//butterknife
apply plugin: 'org.greenrobot.greendao'//greendao
3.在model的最下面新增:
// 配置GreenDao基本引數 greendao { //設定當前資料庫版本 schemaVersion 1 //dao的包名,預設的是entity所在的包 daoPackage '包名+dao' //生成資料庫檔案的目錄 targetGenDir 'src/main/java' }
4.在工程的build中的dependencies裡新增greendao和butterknife的配置:
//butterknife
classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1'
//greendao
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
到這裡,這三個功能已經配置完成了,可以使用了。
2.首先是流失佈局的配置,自定義繼承ViewGroup設定
**1.自定義流式佈局**
public class ReSouView extends ViewGroup {
//儲存所有子View
private List<List<View>> mAllChildViews = new ArrayList<>();
//每一行的高度
private List<Integer> mLineHeight = new ArrayList<>();
public ReSouView(Context context) {
super(context);
}
public ReSouView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ReSouView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mAllChildViews.clear();
mLineHeight.clear();
//獲取當前ViewGroup的寬度
int width = getWidth();
int lineWidth = 0;
int lineHeight = 0;
//記錄當前行的view
List<View> lineViews = new ArrayList<View>();
int childCount = getChildCount();
for(int i = 0;i < childCount; 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){
//記錄LineHeight
mLineHeight.add(lineHeight);
//記錄當前行的Views
mAllChildViews.add(lineViews);
//重置行的寬高
lineWidth = 0;
lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
//重置view的集合
lineViews = new ArrayList();
}
lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);
lineViews.add(child);
}
//處理最後一行
mLineHeight.add(lineHeight);
mAllChildViews.add(lineViews);
//設定子View的位置
int left = 0;
int top = 0;
//獲取行數
int lineCount = mAllChildViews.size();
for(int i = 0; i < lineCount; i ++){
//當前行的views和高度
lineViews = mAllChildViews.get(i);
lineHeight = mLineHeight.get(i);
for(int j = 0; j < lineViews.size(); j ++){
View child = lineViews.get(j);
//判斷是否顯示
if(child.getVisibility() == View.GONE){
continue;
}
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int cLeft = left + lp.leftMargin;
int cTop = top + lp.topMargin;
int cRight = cLeft + child.getMeasuredWidth();
int cBottom = cTop + child.getMeasuredHeight();
//進行子View進行佈局
child.layout(cLeft, cTop, cRight, cBottom);
left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
}
left = 0;
top += lineHeight;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//父控制元件傳進來的寬度和高度以及對應的測量模式
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
//如果當前ViewGroup的寬高為wrap_content的情況
int width = 0;//自己測量的 寬度
int height = 0;//自己測量的高度
//記錄每一行的寬度和高度
int lineWidth = 0;
int lineHeight = 0;
//獲取子view的個數
int childCount = getChildCount();
for(int i = 0;i < childCount; i ++){
View child = getChildAt(i);
//測量子View的寬和高
measureChild(child, widthMeasureSpec, heightMeasureSpec);
//得到LayoutParams
MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
//子View佔據的寬度
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
//子View佔據的高度
int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
//換行時候
if(lineWidth + childWidth > sizeWidth){
//對比得到最大的寬度
width = Math.max(width, lineWidth);
//重置lineWidth
lineWidth = childWidth;
//記錄行高
height += lineHeight;
lineHeight = childHeight;
}else{//不換行情況
//疊加行寬
lineWidth += childWidth;
//得到最大行高
lineHeight = Math.max(lineHeight, childHeight);
}
//處理最後一個子View的情況
if(i == childCount -1){
width = Math.max(width, lineWidth);
height += lineHeight;
}
}
//wrap_content
setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width,
modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height);
}
/**
* 與當前ViewGroup對應的LayoutParams
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
// TODO Auto-generated method stub
return new MarginLayoutParams(getContext(), attrs);
}
}
這就是自定義佈局的流式佈局,然後再佈局中引用。
2.熱搜介面的佈局,在這裡引用流式佈局,顯示京東上熱搜效果
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="shouye.presenter.resou.ReSouActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:id="@+id/btn_back"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:text=" < "/>
<EditText
android:id="@+id/et_sou"
android:layout_width="0dp"
android:layout_weight="4"
android:hint="內衣跨店3免1,服裝跨店3件7折"
android:layout_height="match_parent" />
<TextView
android:onClick="btn_search"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:text="搜尋"/>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="熱搜"
android:textSize="18sp"
android:textStyle="bold"/>
<自己的包名.流式佈局的類名
android:id="@+id/reSouView"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="100dp"></自己的包名.流式佈局的類名>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="歷史記錄"
android:textSize="24dp"
/>
<ListView
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="@+id/lv"
></ListView>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="清空歷史記錄"
android:layout_gravity="center"
android:gravity="center"
android:onClick="delall"
android:visibility="invisible"
android:id="@+id/btn"
/>
</LinearLayout>
3.在熱搜介面進行資料的設定,用greendao增刪改查,用eventbus傳值
package shouye.presenter.resou;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import deom.jingdong.wwx.R;
import deom.jingdong.wwx.dao.DaoMaster;
import deom.jingdong.wwx.dao.DaoSession;
import deom.jingdong.wwx.dao.MySearchBeanDao;
import shouye.model.adapter.GreenDaoAdapter;
import shouye.model.bean.MessageBean;
import shouye.view.SearchActivity;
public class ReSouActivity extends AppCompatActivity {
private static final String TAG = "ReSouActivity";
@BindView(R.id.btn_back)
TextView back;
@BindView(R.id.et_sou)
EditText search_name;
@BindView(R.id.reSouView)
ReSouView reSouView;
@BindView(R.id.lv)
ListView lv;
@BindView(R.id.btn)
Button btn;
private String mNames[] = {
"洗衣機", "娃娃", "山地自行車",
"電冰箱", "水果", "小米手機",
"電腦", "蘋果", "三星",
"電磁爐", "vivo", "oppo"};
private MySearchBeanDao beanDao;
private String name;
private MySearchBean mySearchBean;
private List<MySearchBean> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_re_sou);
ButterKnife.bind(this);
//初始化greendao
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(getApplicationContext(), "green_dao.db", null);
DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());
DaoSession daoSession = daoMaster.newSession();
beanDao = daoSession.getMySearchBeanDao();
//熱搜
initChildViews();
//進入就查詢展示
inSelect();
//返回
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
//點選條目將值賦給搜尋框
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView textView = view.findViewById(android.R.id.text1);
String string = textView.getText().toString();
search_name.setText(string);
Toast.makeText(ReSouActivity.this, string, Toast.LENGTH_SHORT).show();
}
});
}
/**
* 搜尋介面回傳過來的值
*
* @param messageBean
*/
public void onEventMainThread(MessageBean messageBean) {
search_name.setText(messageBean.getMessage());
}
/**
* 點選刪除
*
* @param view
*/
public void delall(View view) {
beanDao.deleteAll();
inSelect();
}
/**
* 點選查詢
*
* @param view
*/
public void btn_search(View view) {
name = search_name.getText().toString();
//新增到greendao
mySearchBean = new MySearchBean(null, name);
beanDao.insert(mySearchBean);
Log.i(TAG, "新增的資料是:" + mySearchBean.getName());
//新增之後查詢
inSelect();
//eventbus跳轉傳值
startActivity(new Intent(this, SearchActivity.class));
MessageBean messageBean = new MessageBean();
messageBean.setMessage(name);
//粘性事件傳值
EventBus.getDefault().postSticky(messageBean);
}
/**
* 查詢出展示資料的方法
*/
private void inSelect() {
//再查詢展示出來
list = beanDao.queryBuilder().build().list();
//用baseadapter顯示資料
GreenDaoAdapter adapter = new GreenDaoAdapter(this, list);
lv.setAdapter(adapter);
if (list.size() >= 1) {
btn.setVisibility(View.VISIBLE);
}
}
private void initChildViews() {
// TODO Auto-generated method stub
reSouView = findViewById(R.id.reSouView);
ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.leftMargin = 5;
lp.rightMargin = 5;
lp.topMargin = 5;
lp.bottomMargin = 5;
for (int i = 0; i < mNames.length; i++) {
TextView view = new TextView(this);
view.setText(mNames[i]);
view.setTextColor(Color.WHITE);
view.setBackgroundDrawable(getResources().getDrawable(R.drawable.textshape));
reSouView.addView(view, lp);
}
}
}
4.建立一個普通的bean類,通過註解建立SQL資料表。
package shouye.presenter.resou;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
/**
* Created by Administrator on 2018/4/28,0028.
*/
@Entity
public class MySearchBean {
@Id(autoincrement = true)
Long id;
@Property
String name;
@Generated(hash = 1426885630)
public MySearchBean() {
}
@Generated(hash = 1256736245)
public MySearchBean(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
5.建立好之後在工具類點選Build裡面的Make Pregress 或者(Ctrl+9)自動生成三個類,比如:
6.因為要用EventBus傳值,所以在接收值的頁面進行EventBus的註冊和反註冊。
package shouye.view;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List;
import shouye.model.adapter.GridAdapter;
import shouye.model.adapter.LinearAdapter;
import shouye.model.bean.MessageBean;
import shouye.model.bean.SearchBean;
import deom.jingdong.wwx.R;
import shouye.presenter.SearchPresenter;
import utils.Api;
import shouye.view.IView.ISearchView;
public class SearchActivity extends AppCompatActivity implements ISearchView {
private TextView edit_search;
private CheckBox checkbox;
private RecyclerView recyclerView;
private SearchPresenter searchPresenter;
private String keywords;
private List<SearchBean.DataBean> list;
private LinearAdapter adapter;
private GridAdapter gridadapter;
boolean flag = false;
private TextView back;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
setContentView(R.layout.activity_search);
findView();
//註冊EventBus
EventBus.getDefault().register(this);
searchPresenter = new SearchPresenter();
searchPresenter.attachView(this);
keywords = edit_search.getText().toString();
if (keywords == null) {
Toast.makeText(SearchActivity.this, "請輸入搜尋的內容", Toast.LENGTH_SHORT).show();
} else {
searchPresenter.getData(Api.SEARCH_API, keywords);
}
}
/**
* 將值用EventBus傳過來
* @param messageBean
*/
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onRec(MessageBean messageBean) {
edit_search.setText(messageBean.getMessage());
}
private void findView() {
back = findViewById(R.id.search_back);
edit_search = findViewById(R.id.edit_search);
checkbox = findViewById(R.id.checkbox);
recyclerView = findViewById(R.id.reycleView);
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
edit_search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//點選搜尋框回傳值
EventBus.getDefault().post(new MessageBean(keywords));
finish();
}
});
}
/**
* 重新的方法
*
* @param dataDataBean
*/
@Override
public void onSuccess(final SearchBean dataDataBean) {
runOnUiThread(new Runnable() {
@Override
public void run() {
list = dataDataBean.getData();
if (dataDataBean.getCode().equals("0")) {
setAdapter(list);
Toast.makeText(SearchActivity.this, dataDataBean.getMsg(), Toast.LENGTH_SHORT).show();
checkbox.setChecked(flag);//預設未點選
checkbox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (flag) {
//設定介面卡
setAdapter(list);
checkbox.setChecked(false);
flag = checkbox.isChecked();
} else {
gridadapter = new GridAdapter(SearchActivity.this, list);
recyclerView.setAdapter(gridadapter);
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
checkbox.setChecked(true);
flag = checkbox.isChecked();
//給介面卡設定點選事件
gridadapter.setOnItemClick(new LinearAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(SearchActivity.this, "點選" + position, Toast.LENGTH_SHORT).show();
}
});
}
}
});
} else {
Toast.makeText(SearchActivity.this, "輸入有誤", Toast.LENGTH_SHORT).show();
}
}
});
}
private void setAdapter(List<SearchBean.DataBean> list) {
adapter = new LinearAdapter(SearchActivity.this, list);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(SearchActivity.this, LinearLayoutManager.VERTICAL, false));
//給介面卡設定點選事件
adapter.setOnItemClick(new LinearAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
if (searchPresenter != null) {
searchPresenter.dettachView();
}
}
}