Android自定义流式布局实现淘宝搜索记录

本文实例为大家分享了Android实现淘宝搜索记录的具体代码,供大家参考,具体内容如下

效果如下:

Android自定义流式布局实现淘宝搜索记录_第1张图片

Android自定义流式布局实现淘宝搜索记录_第2张图片

Android自定义流式布局实现淘宝搜索记录_第3张图片

废话不多说

实现代码:

attrs.xml


 
 
 
 
 
 
 
  
  
  
 

TagFlowLayout .java

public class TagFlowLayout extends FlowLayout
 implements TagAdapter.OnDataChangedListener {

 private static final String TAG = "TagFlowLayout";
 private TagAdapter mTagAdapter;
 private int mSelectedMax = -1;//-1为不限制数量

 private Set mSelectedView = new HashSet();

 private OnSelectListener mOnSelectListener;
 private OnTagClickListener mOnTagClickListener;
 private OnLongClickListener mOnLongClickListener;

 public interface OnSelectListener {
 void onSelected(Set selectPosSet);
 }

 public interface OnTagClickListener {
 void onTagClick(View view, int position, FlowLayout parent);
 }

 public interface OnLongClickListener {
 void onLongClick(View view, int position);
 }

 public TagFlowLayout(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TagFlowLayout);
 mSelectedMax = ta.getInt(R.styleable.TagFlowLayout_max_select, -1);
 ta.recycle();
 }

 public TagFlowLayout(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
 }

 public TagFlowLayout(Context context) {
 this(context, null);
 }


 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 int cCount = getChildCount();
 for (int i = 0; i < cCount; i++) {
  TagView tagView = (TagView) getChildAt(i);
  if (tagView.getVisibility() == View.GONE) {
  continue;
  }
  if (tagView.getTagView().getVisibility() == View.GONE) {
  tagView.setVisibility(View.GONE);
  }
 }
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 }


 public void setOnSelectListener(OnSelectListener onSelectListener) {
 mOnSelectListener = onSelectListener;
 }


 public void setOnTagClickListener(OnTagClickListener onTagClickListener) {
 mOnTagClickListener = onTagClickListener;
 }

 public void setOnLongClickListener(OnLongClickListener onLongClickListener) {
 mOnLongClickListener = onLongClickListener;
 }

 public void setAdapter(TagAdapter adapter) {
 mTagAdapter = adapter;
 mTagAdapter.setOnDataChangedListener(this);
 mSelectedView.clear();
 changeAdapter();
 }

 @SuppressWarnings("ResourceType")
 private void changeAdapter() {
 removeAllViews();
 TagAdapter adapter = mTagAdapter;
 TagView tagViewContainer = null;
 HashSet preCheckedList = mTagAdapter.getPreCheckedList();
 for (int i = 0; i < adapter.getCount(); i++) {
  View tagView = adapter.getView(this, i, adapter.getItem(i));

  tagViewContainer = new TagView(getContext());
  tagView.setDuplicateParentStateEnabled(true);
  if (tagView.getLayoutParams() != null) {
  tagViewContainer.setLayoutParams(tagView.getLayoutParams());


  } else {
  MarginLayoutParams lp = new MarginLayoutParams(
   LayoutParams.WRAP_CONTENT,
   LayoutParams.WRAP_CONTENT);
  lp.setMargins(dip2px(getContext(), 5),
   dip2px(getContext(), 5),
   dip2px(getContext(), 5),
   dip2px(getContext(), 5));
  tagViewContainer.setLayoutParams(lp);
  }
  LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
  tagView.setLayoutParams(lp);
  tagViewContainer.addView(tagView);
  addView(tagViewContainer);

  if (preCheckedList.contains(i)) {
  setChildChecked(i, tagViewContainer);
  }

  if (mTagAdapter.setSelected(i, adapter.getItem(i))) {
  setChildChecked(i, tagViewContainer);
  }
  tagView.setClickable(false);
  final TagView finalTagViewContainer = tagViewContainer;
  final int position = i;
  tagViewContainer.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
   doSelect(finalTagViewContainer, position);
   if (mOnTagClickListener != null) {
   mOnTagClickListener.onTagClick(finalTagViewContainer, position,
    TagFlowLayout.this);
   }
  }
  });

  tagViewContainer.setOnLongClickListener(new View.OnLongClickListener() {
  @Override
  public boolean onLongClick(View v) {
   if (mOnLongClickListener != null) {
   mOnLongClickListener.onLongClick(finalTagViewContainer, position);
   //消费事件,不让事件继续下去
   return true;
   }
   return false;
  }
  });
 }
 mSelectedView.addAll(preCheckedList);
 }

 public void setMaxSelectCount(int count) {
 if (mSelectedView.size() > count) {
  Log.w(TAG, "you has already select more than " + count + " views , so it will be clear .");
  mSelectedView.clear();
 }
 mSelectedMax = count;
 }

 public Set getSelectedList() {
 return new HashSet(mSelectedView);
 }

 private void setChildChecked(int position, TagView view) {
 view.setChecked(true);
 mTagAdapter.onSelected(position, view.getTagView());
 }

 private void setChildUnChecked(int position, TagView view) {
 view.setChecked(false);
 mTagAdapter.unSelected(position, view.getTagView());
 }

 private void doSelect(TagView child, int position) {
 if (!child.isChecked()) {
  //处理max_select=1的情况
  if (mSelectedMax == 1 && mSelectedView.size() == 1) {
  Iterator iterator = mSelectedView.iterator();
  Integer preIndex = iterator.next();
  TagView pre = (TagView) getChildAt(preIndex);
  setChildUnChecked(preIndex, pre);
  setChildChecked(position, child);

  mSelectedView.remove(preIndex);
  mSelectedView.add(position);
  } else {
  if (mSelectedMax > 0 && mSelectedView.size() >= mSelectedMax) {
   return;
  }
  setChildChecked(position, child);
  mSelectedView.add(position);
  }
 } else {
  setChildUnChecked(position, child);
  mSelectedView.remove(position);
 }
 if (mOnSelectListener != null) {
  mOnSelectListener.onSelected(new HashSet(mSelectedView));
 }
 }

 public TagAdapter getAdapter() {
 return mTagAdapter;
 }


 private static final String KEY_CHOOSE_POS = "key_choose_pos";
 private static final String KEY_DEFAULT = "key_default";


 @Override
 protected Parcelable onSaveInstanceState() {
 Bundle bundle = new Bundle();
 bundle.putParcelable(KEY_DEFAULT, super.onSaveInstanceState());

 String selectPos = "";
 if (mSelectedView.size() > 0) {
  for (int key : mSelectedView) {
  selectPos += key + "|";
  }
  selectPos = selectPos.substring(0, selectPos.length() - 1);
 }
 bundle.putString(KEY_CHOOSE_POS, selectPos);
 return bundle;
 }

 @Override
 protected void onRestoreInstanceState(Parcelable state) {
 if (state instanceof Bundle) {
  Bundle bundle = (Bundle) state;
  String mSelectPos = bundle.getString(KEY_CHOOSE_POS);
  if (!TextUtils.isEmpty(mSelectPos)) {
  String[] split = mSelectPos.split("\\|");
  for (String pos : split) {
   int index = Integer.parseInt(pos);
   mSelectedView.add(index);

   TagView tagView = (TagView) getChildAt(index);
   if (tagView != null) {
   setChildChecked(index, tagView);
   }
  }
  }
  super.onRestoreInstanceState(bundle.getParcelable(KEY_DEFAULT));
  return;
 }
 super.onRestoreInstanceState(state);
 }


 @Override
 public void onChanged() {
 mSelectedView.clear();
 changeAdapter();
 }

 public static int dip2px(Context context, float dpValue) {
 final float scale = context.getResources().getDisplayMetrics().density;
 return (int) (dpValue * scale + 0.5f);
 }
}

TagView

public class TagView extends FrameLayout implements Checkable
{
 private boolean isChecked;
 private static final int[] CHECK_STATE = new int[]{android.R.attr.state_checked};

 public TagView(Context context)
 {
 super(context);
 }

 public View getTagView()
 {
 return getChildAt(0);
 }

 @Override
 public int[] onCreateDrawableState(int extraSpace)
 {
 int[] states = super.onCreateDrawableState(extraSpace + 1);
 if (isChecked())
 {
  mergeDrawableStates(states, CHECK_STATE);
 }
 return states;
 }


 /**
 * Change the checked state of the view
 *
 * @param checked The new checked state
 */
 @Override
 public void setChecked(boolean checked)
 {
 if (this.isChecked != checked)
 {
  this.isChecked = checked;
  refreshDrawableState();
 }
 }

 /**
 * @return The current checked state of the view
 */
 @Override
 public boolean isChecked()
 {
 return isChecked;
 }

 /**
 * Change the checked state of the view to the inverse of its current state
 */
 @Override
 public void toggle()
 {
 setChecked(!isChecked);
 }


}

FlowLayout

public class FlowLayout extends ViewGroup {
 private static final String TAG = "FlowLayout";
 private static final int LEFT = -1;
 private static final int CENTER = 0;
 private static final int RIGHT = 1;

 private int limitLineCount; //默认显示3行 断词条显示3行,长词条显示2行
 private boolean isLimit; //是否有行限制
 private boolean isOverFlow; //是否溢出2行

 private int mGravity;
 protected List> mAllViews = new ArrayList>();
 protected List mLineHeight = new ArrayList();
 protected List mLineWidth = new ArrayList();
 private List lineViews = new ArrayList<>();

 public boolean isOverFlow() {
 return isOverFlow;
 }

 private void setOverFlow(boolean overFlow) {
 isOverFlow = overFlow;
 }

 public boolean isLimit() {
 return isLimit;
 }

 public void setLimit(boolean limit) {
 if (!limit) {
  setOverFlow(false);
 }
 isLimit = limit;
 }

 public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TagFlowLayout);
 mGravity = ta.getInt(R.styleable.TagFlowLayout_tag_gravity, LEFT);
 limitLineCount = ta.getInt(R.styleable.TagFlowLayout_limit_line_count, 3);
 isLimit = ta.getBoolean(R.styleable.TagFlowLayout_is_limit, false);
 int layoutDirection = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault());
 if (layoutDirection == LayoutDirection.RTL) {
  if (mGravity == LEFT) {
  mGravity = RIGHT;
  } else {
  mGravity = LEFT;
  }
 }
 ta.recycle();
 }

 public FlowLayout(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
 }

 public FlowLayout(Context context) {
 this(context, null);
 }

 @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);

 // wrap_content
 int width = 0;
 int height = 0;

 int lineWidth = 0;
 int lineHeight = 0;

 //在每一次换行之后记录,是否超过了行数
 int lineCount = 0;//记录当前的行数

 int cCount = getChildCount();

 for (int i = 0; i < cCount; i++) {
  View child = getChildAt(i);
  if (child.getVisibility() == View.GONE) {
  if (i == cCount - 1) {
   if (isLimit) {
   if (lineCount == limitLineCount) {
    setOverFlow(true);
    break;
   } else {
    setOverFlow(false);
   }
   }

   width = Math.max(lineWidth, width);
   height += lineHeight;
   lineCount++;
  }
  continue;
  }
  measureChild(child, widthMeasureSpec, heightMeasureSpec);
  MarginLayoutParams lp = (MarginLayoutParams) child
   .getLayoutParams();

  int childWidth = child.getMeasuredWidth() + lp.leftMargin
   + lp.rightMargin;
  int childHeight = child.getMeasuredHeight() + lp.topMargin
   + lp.bottomMargin;

  if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) {
  if (isLimit) {
   if (lineCount == limitLineCount) {
   setOverFlow(true);
   break;
   } else {
   setOverFlow(false);
   }
  }
  width = Math.max(width, lineWidth);
  lineWidth = childWidth;
  height += lineHeight;
  lineHeight = childHeight;
  lineCount++;
  } else {
  lineWidth += childWidth;
  lineHeight = Math.max(lineHeight, childHeight);
  }
  if (i == cCount - 1) {
  if (isLimit) {
   if (lineCount == limitLineCount) {
   setOverFlow(true);
   break;
   } else {
   setOverFlow(false);
   }
  }
  width = Math.max(lineWidth, width);
  height += lineHeight;
  lineCount++;
  }
 }
 setMeasuredDimension(
  modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width + getPaddingLeft() + getPaddingRight(),
  modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height + getPaddingTop() + getPaddingBottom()//
 );
 }


 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
 mAllViews.clear();
 mLineHeight.clear();
 mLineWidth.clear();
 lineViews.clear();

 int width = getWidth();

 int lineWidth = 0;
 int lineHeight = 0;

 //如果超过规定的行数则不进行绘制
 int lineCount = 0;//记录当前的行数

 int cCount = getChildCount();

 for (int i = 0; i < cCount; i++) {
  View child = getChildAt(i);
  if (child.getVisibility() == View.GONE) continue;
  MarginLayoutParams lp = (MarginLayoutParams) child
   .getLayoutParams();

  int childWidth = child.getMeasuredWidth();
  int childHeight = child.getMeasuredHeight();

  if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width - getPaddingLeft() - getPaddingRight()) {
  if (isLimit) {
   if (lineCount == limitLineCount) {
   break;
   }
  }

  mLineHeight.add(lineHeight);
  mAllViews.add(lineViews);
  mLineWidth.add(lineWidth);

  lineWidth = 0;
  lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
  lineViews = new ArrayList();
  lineCount++;
  }
  lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
  lineHeight = Math.max(lineHeight, childHeight + lp.topMargin
   + lp.bottomMargin);
  lineViews.add(child);

 }
 mLineHeight.add(lineHeight);
 mLineWidth.add(lineWidth);
 mAllViews.add(lineViews);


 int left = getPaddingLeft();
 int top = getPaddingTop();

 int lineNum = mAllViews.size();

 for (int i = 0; i < lineNum; i++) {
  lineViews = mAllViews.get(i);
  lineHeight = mLineHeight.get(i);

  // set gravity
  int currentLineWidth = this.mLineWidth.get(i);
  switch (this.mGravity) {
  case LEFT:
   left = getPaddingLeft();
   break;
  case CENTER:
   left = (width - currentLineWidth) / 2 + getPaddingLeft();
   break;
  case RIGHT:
   // 适配了rtl,需要补偿一个padding值
   left = width - (currentLineWidth + getPaddingLeft()) - getPaddingRight();
   // 适配了rtl,需要把lineViews里面的数组倒序排
   Collections.reverse(lineViews);
   break;
  }

  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 lc = left + lp.leftMargin;
  int tc = top + lp.topMargin;
  int rc = lc + child.getMeasuredWidth();
  int bc = tc + child.getMeasuredHeight();

  child.layout(lc, tc, rc, bc);

  left += child.getMeasuredWidth() + lp.leftMargin
   + lp.rightMargin;
  }
  top += lineHeight;
 }

 }

 @Override
 public LayoutParams generateLayoutParams(AttributeSet attrs) {
 return new MarginLayoutParams(getContext(), attrs);
 }

 @Override
 protected LayoutParams generateDefaultLayoutParams() {
 return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
 }

 @Override
 protected LayoutParams generateLayoutParams(LayoutParams p) {
 return new MarginLayoutParams(p);
 }
}

TagAdapter

public abstract class TagAdapter {
 private List mTagDatas;
 private OnDataChangedListener mOnDataChangedListener;
 @Deprecated
 private HashSet mCheckedPosList = new HashSet();

 public TagAdapter(List datas) {
 mTagDatas = datas;
 }

 public void setData(List datas) {
 mTagDatas = datas;
 }

 @Deprecated
 public TagAdapter(T[] datas) {
 mTagDatas = new ArrayList(Arrays.asList(datas));
 }

 interface OnDataChangedListener {
 void onChanged();
 }

 void setOnDataChangedListener(OnDataChangedListener listener) {
 mOnDataChangedListener = listener;
 }

 @Deprecated
 public void setSelectedList(int... poses) {
 Set set = new HashSet<>();
 for (int pos : poses) {
  set.add(pos);
 }
 setSelectedList(set);
 }

 @Deprecated
 public void setSelectedList(Set set) {
 mCheckedPosList.clear();
 if (set != null) {
  mCheckedPosList.addAll(set);
 }
 notifyDataChanged();
 }

 @Deprecated
 HashSet getPreCheckedList() {
 return mCheckedPosList;
 }


 public int getCount() {
 return mTagDatas == null ? 0 : mTagDatas.size();
 }

 public void notifyDataChanged() {
 if (mOnDataChangedListener != null)
  mOnDataChangedListener.onChanged();
 }

 public T getItem(int position) {
 return mTagDatas.get(position);
 }

 public abstract View getView(FlowLayout parent, int position, T t);


 public void onSelected(int position, View view) {
 Log.d("zhy", "onSelected " + position);
 }

 public void unSelected(int position, View view) {
 Log.d("zhy", "unSelected " + position);
 }

 public boolean setSelected(int position, T t) {
 return false;
 }
}

RecordsDao

public class RecordsDao {
 private final String TABLE_NAME = "records";
 private SQLiteDatabase recordsDb;
 private RecordSQLiteOpenHelper recordHelper;
 private NotifyDataChanged mNotifyDataChanged;
 private String mUsername;

 public RecordsDao(Context context, String username) {
 recordHelper = new RecordSQLiteOpenHelper(context);
 mUsername = username;
 }

 public interface NotifyDataChanged {
 void notifyDataChanged();
 }

 /**
 * 设置数据变化监听
 */
 public void setNotifyDataChanged(NotifyDataChanged notifyDataChanged) {
 mNotifyDataChanged = notifyDataChanged;
 }

 /**
 * 移除数据变化监听
 */
 public void removeNotifyDataChanged() {
 if (mNotifyDataChanged != null) {
  mNotifyDataChanged = null;
 }
 }

 private synchronized SQLiteDatabase getWritableDatabase() {
 return recordHelper.getWritableDatabase();
 }

 private synchronized SQLiteDatabase getReadableDatabase() {
 return recordHelper.getReadableDatabase();
 }

 /**
 * 如果考虑操作频繁可以到最后不用数据库时关闭
 * 

* 关闭数据库 */ public void closeDatabase() { if (recordsDb != null) { recordsDb.close(); } } /** * 添加搜索记录 * * @param record 记录 */ public void addRecords(String record) { //如果这条记录没有则添加,有则更新时间 int recordId = getRecordId(record); try { recordsDb = getReadableDatabase(); if (-1 == recordId) { ContentValues values = new ContentValues(); values.put("username", mUsername); values.put("keyword", record); //添加搜索记录 recordsDb.insert(TABLE_NAME, null, values); } else { Date d = new Date(); @SuppressLint("SimpleDateFormat") SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //更新搜索历史数据时间 ContentValues values = new ContentValues(); values.put("time", sdf.format(d)); recordsDb.update(TABLE_NAME, values, "_id = ?", new String[]{Integer.toString(recordId)}); } if (mNotifyDataChanged != null) { mNotifyDataChanged.notifyDataChanged(); } } catch (Exception e) { e.printStackTrace(); } } /** * 判断是否含有该搜索记录 * * @param record 记录 * @return true | false */ public boolean isHasRecord(String record) { boolean isHasRecord = false; Cursor cursor = null; try { recordsDb = getReadableDatabase(); cursor = recordsDb.query(TABLE_NAME, null, "username = ?", new String[]{mUsername}, null, null, null); while (cursor.moveToNext()) { if (record.equals(cursor.getString(cursor.getColumnIndexOrThrow("keyword")))) { isHasRecord = true; } } } catch (IllegalArgumentException e) { e.printStackTrace(); } finally { if (cursor != null) { //关闭游标 cursor.close(); } } return isHasRecord; } /** * 判断是否含有该搜索记录 * * @param record 记录 * @return id */ public int getRecordId(String record) { int isHasRecord = -1; Cursor cursor = null; try { recordsDb = getReadableDatabase(); cursor = recordsDb.query(TABLE_NAME, null, "username = ?", new String[]{mUsername}, null, null, null); while (cursor.moveToNext()) { if (record.equals(cursor.getString(cursor.getColumnIndexOrThrow("keyword")))) { isHasRecord = cursor.getInt(cursor.getColumnIndexOrThrow("_id")); } } } catch (IllegalArgumentException e) { e.printStackTrace(); } finally { if (cursor != null) { //关闭游标 cursor.close(); } } return isHasRecord; } /** * 获取当前用户全部搜索记录 * * @return 记录集合 */ public List getRecordsList() { List recordsList = new ArrayList<>(); Cursor cursor = null; try { recordsDb = getReadableDatabase(); cursor = recordsDb.query(TABLE_NAME, null, "username = ?", new String[]{mUsername}, null, null, "time desc"); while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndexOrThrow("keyword")); recordsList.add(name); } } catch (IllegalArgumentException e) { e.printStackTrace(); } finally { if (cursor != null) { //关闭游标 cursor.close(); } } return recordsList; } /** * 获取指定数量搜索记录 * * @return 记录集合 */ public List getRecordsByNumber(int recordNumber) { List recordsList = new ArrayList<>(); if (recordNumber < 0) { throw new IllegalArgumentException(); } else if (0 == recordNumber) { return recordsList; } else { Cursor cursor = null; try { recordsDb = getReadableDatabase(); cursor = recordsDb.query(TABLE_NAME, null, "username = ?", new String[]{mUsername}, null, null, "time desc limit " + recordNumber); while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndexOrThrow("keyword")); recordsList.add(name); } } catch (IllegalArgumentException e) { e.printStackTrace(); } finally { if (cursor != null) { //关闭游标 cursor.close(); } } } return recordsList; } /** * 模糊查询 * * @param record 记录 * @return 返回类似记录 */ public List querySimlarRecord(String record) { List similarRecords = new ArrayList<>(); Cursor cursor = null; try { recordsDb = getReadableDatabase(); cursor = recordsDb.query(TABLE_NAME, null, "username = ? and keyword like '%?%'", new String[]{mUsername, record}, null, null, "order by time desc"); while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndexOrThrow("keyword")); similarRecords.add(name); } } catch (IllegalArgumentException e) { e.printStackTrace(); } finally { if (cursor != null) { //关闭游标 cursor.close(); } } return similarRecords; } /** * 清除指定用户的搜索记录 */ public void deleteUsernameAllRecords() { try { recordsDb = getWritableDatabase(); recordsDb.delete(TABLE_NAME, "username = ?", new String[]{mUsername}); if (mNotifyDataChanged != null) { mNotifyDataChanged.notifyDataChanged(); } } catch (SQLException e) { e.printStackTrace(); Log.e(TABLE_NAME, "清除所有历史记录失败"); } finally { } } /** * 清空数据库所有的历史记录 */ public void deleteAllRecords() { try { recordsDb = getWritableDatabase(); recordsDb.execSQL("delete from " + TABLE_NAME); if (mNotifyDataChanged != null) { mNotifyDataChanged.notifyDataChanged(); } } catch (SQLException e) { e.printStackTrace(); Log.e(TABLE_NAME, "清除所有历史记录失败"); } finally { } } /** * 通过id删除记录 * * @param id 记录id * @return 返回删除id */ public int deleteRecord(int id) { int d = -1; try { recordsDb = getWritableDatabase(); d = recordsDb.delete(TABLE_NAME, "_id = ?", new String[]{Integer.toString(id)}); if (mNotifyDataChanged != null) { mNotifyDataChanged.notifyDataChanged(); } } catch (Exception e) { e.printStackTrace(); Log.e(TABLE_NAME, "删除_id:" + id + "历史记录失败"); } return d; } /** * 通过记录删除记录 * * @param record 记录 */ public int deleteRecord(String record) { int recordId = -1; try { recordsDb = getWritableDatabase(); recordId = recordsDb.delete(TABLE_NAME, "username = ? and keyword = ?", new String[]{mUsername, record}); if (mNotifyDataChanged != null) { mNotifyDataChanged.notifyDataChanged(); } } catch (SQLException e) { e.printStackTrace(); Log.e(TABLE_NAME, "清除所有历史记录失败"); } return recordId; } }

RecordSQLiteOpenHelper

public class RecordSQLiteOpenHelper extends SQLiteOpenHelper {
 private final static String DB_NAME = "search_history.db";
 private final static int DB_VERSION = 1;

 public RecordSQLiteOpenHelper(Context context) {
 super(context, DB_NAME, null, DB_VERSION);
 }

 @Override
 public void onCreate(SQLiteDatabase db) {
 String sqlStr = "CREATE TABLE IF NOT EXISTS records (_id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT, keyword TEXT, time NOT NULL DEFAULT (datetime('now','localtime')));";
 db.execSQL(sqlStr);
 }

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

 }
}

item_background.xml



 
 

 

 

search_item_background.xml



 
 

 

 

tv_history.xml


activity_main.xml



 
 

 

 

  

  
 

 
 

 
 

 

  

  
 

 
 

 
 

MainActivity.java

public class MainActivity extends AppCompatActivity {

 private RecordsDao mRecordsDao;
 //默然展示词条个数
 private final int DEFAULT_RECORD_NUMBER = 10;
 private List recordList = new ArrayList<>();
 private TagAdapter mRecordsAdapter;
 private LinearLayout mHistoryContent;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 //默认账号
 String username = "007";
 //初始化数据库
 mRecordsDao = new RecordsDao(this, username);

 final EditText editText = findViewById(R.id.edit_query);
 final TagFlowLayout tagFlowLayout = findViewById(R.id.fl_search_records);
 final ImageView clearAllRecords = findViewById(R.id.clear_all_records);
 final ImageView moreArrow = findViewById(R.id.iv_arrow);
 TextView search = findViewById(R.id.iv_search);
 ImageView clearSearch = findViewById(R.id.iv_clear_search);
 mHistoryContent = findViewById(R.id.ll_history_content);

 initData();

 //创建历史标签适配器
 //为标签设置对应的内容
 mRecordsAdapter = new TagAdapter(recordList) {

  @Override
  public View getView(FlowLayout parent, int position, String s) {
  TextView tv = (TextView) LayoutInflater.from(MainActivity.this).inflate(R.layout.tv_history,
   tagFlowLayout, false);
  //为标签设置对应的内容
  tv.setText(s);
  return tv;
  }
 };


 tagFlowLayout.setAdapter(mRecordsAdapter);
 tagFlowLayout.setOnTagClickListener(new TagFlowLayout.OnTagClickListener() {
  @Override
  public void onTagClick(View view, int position, FlowLayout parent) {
  //清空editText之前的数据
  editText.setText("");
  //将获取到的字符串传到搜索结果界面,点击后搜索对应条目内容
  editText.setText(recordList.get(position));
  editText.setSelection(editText.length());
  }
 });
 //删除某个条目
 tagFlowLayout.setOnLongClickListener(new TagFlowLayout.OnLongClickListener() {
  @Override
  public void onLongClick(View view, final int position) {
  showDialog("确定要删除该条历史记录?", new DialogInterface.OnClickListener() {
   @Override
   public void onClick(DialogInterface dialog, int which) {
   //删除某一条记录
   mRecordsDao.deleteRecord(recordList.get(position));
   }
  });
  }
 });

 //view加载完成时回调
 tagFlowLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
  boolean isOverFlow = tagFlowLayout.isOverFlow();
  boolean isLimit = tagFlowLayout.isLimit();
  if (isLimit && isOverFlow) {
   moreArrow.setVisibility(View.VISIBLE);
  } else {
   moreArrow.setVisibility(View.GONE);
  }
  }
 });

 moreArrow.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  tagFlowLayout.setLimit(false);
  mRecordsAdapter.notifyDataChanged();
  }
 });

 //清除所有记录
 clearAllRecords.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  showDialog("确定要删除全部历史记录?", new DialogInterface.OnClickListener() {
   @Override
   public void onClick(DialogInterface dialog, int which) {
   tagFlowLayout.setLimit(true);
   //清除所有数据
   mRecordsDao.deleteUsernameAllRecords();
   }
  });
  }
 });

 search.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  String record = editText.getText().toString();
  if (!TextUtils.isEmpty(record)) {
   //添加数据
   mRecordsDao.addRecords(record);
  }
  }
 });

 clearSearch.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  //清除搜索历史
  editText.setText("");
  }
 });

 mRecordsDao.setNotifyDataChanged(new RecordsDao.NotifyDataChanged() {
  @Override
  public void notifyDataChanged() {
  initData();
  }
 });
 }

 private void showDialog(String dialogTitle, @NonNull DialogInterface.OnClickListener onClickListener) {
 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
 builder.setMessage(dialogTitle);
 builder.setPositiveButton("确定", onClickListener);
 builder.setNegativeButton("取消", null);
 builder.create().show();
 }

 private void initData() {
 Observable.create(new ObservableOnSubscribe>() {
  @Override
  public void subscribe(ObservableEmitter> emitter) throws Exception {
  emitter.onNext(mRecordsDao.getRecordsByNumber(DEFAULT_RECORD_NUMBER));
  }
 }).subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Consumer>() {
   @Override
   public void accept(List s) throws Exception {
   recordList.clear();
   recordList = s;
   if (null == recordList || recordList.size() == 0) {
    mHistoryContent.setVisibility(View.GONE);
   } else {
    mHistoryContent.setVisibility(View.VISIBLE);
   }
   if (mRecordsAdapter != null) {
    mRecordsAdapter.setData(recordList);
    mRecordsAdapter.notifyDataChanged();
   }
   }
  });
 }


 @Override
 protected void onDestroy() {
 mRecordsDao.closeDatabase();
 mRecordsDao.removeNotifyDataChanged();
 super.onDestroy();
 }
}

欢迎大家点赞,评论!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

你可能感兴趣的:(Android自定义流式布局实现淘宝搜索记录)