笔记:MaterialDesign(二)--控/组件简单使用
2018-05-10 本文已影响52人
RoJacKing
MaterialDesign学习笔记,学习共勉
MaterialDesign笔记(一)--控/组件简单使用
MaterialDesign笔记(二)--控/组件简单使用
一、ItemTouchHelper的简单使用
1、MainActivity.java
public class MainActivity extends AppCompatActivity implements ItemDragListener {
private List<String> mData = new ArrayList<>();
private RecyclerView mRv;
private ItemTouchHelperAdapter mAdapter;//adapter
private MyItemTouchHelperCallback mCallback;//自定义触摸回调
private ItemTouchHelper mItemTouchHelper;//系统的
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRv = (RecyclerView) findViewById(R.id.rv);
initData();
// initDecoration();//初始化修饰布局(首字母提示)
initRecyclerView();
}
//初始化修饰布局(首字母提示),效果不友好所以注释了,没有加pinyin4j包就不要打开注释
//如果要打开就加这段依赖compile 'com.github.open-android:pinyin4j:2.5.0'
// private void initDecoration() {
// MyDecorationThree decorationThree = new MyDecorationThree(this, mData);
// mRv.addItemDecoration(decorationThree);
// }
//初始化数据
private void initData() {
for (int i = 0; i < Cheeses.NAMES.length; i++) {
mData.add(Cheeses.NAMES[i]);
}
}
//初始化recyclerview,关联adapter
private void initRecyclerView() {
//普通的 recyclerview与adapter关联
//因为mainactivity实现了ItemDragListener接口,所以可以传this,代表ItemDragListener
mAdapter = new ItemTouchHelperAdapter(mData,this);
mRv.setLayoutManager(new LinearLayoutManager(this));
mRv.setAdapter(mAdapter);
//给recyclerview.adapter设置触摸回调ItemTouchHelper.Callback
// (这个是我们自定义的MyItemTouchHelperCallback)
mCallback = new MyItemTouchHelperCallback(mAdapter);
mItemTouchHelper = new ItemTouchHelper(mCallback);
mItemTouchHelper.attachToRecyclerView(mRv);//绑定触摸回调
}
/**
* imageview的触摸回调
*
* 示例:ItemTouchHelper.startDrag() 只是示例,不要可去除这个方法
* 功能: 按下imageview就可以实现拖拽功能
* 说明:实现这个回调方法----执行ItemTouchHelper.startDrag()---就会
* 执行ItemTouchHelper.Callback----就会执行我们自定义的MyItemTouchHelperCallback)
*
* @param viewHolder
*/
@Override
public void onStartDrags(RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);//系统方法ItemTouchHelper.startDrag()
}
}
2、activity.xml
<?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">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
3、Adapter--ItemTouchHelperAdapter.java
/**
* Created by ${chenyuexueer}
*
* 说明:普通的 RecyclerView.Adapter 只是在里面添加了几个触摸回调的方法
*/
public class ItemTouchHelperAdapter extends RecyclerView.Adapter<ItemTouchHelperAdapter.ItemTouchHelperViewHolder> implements ItemMoveListener {
private List<String> mData;//数据
private ItemDragListener mItemDragListener;//imageview的触摸回调
//构造方法,初始化数据等
public ItemTouchHelperAdapter(List<String> mData, ItemDragListener mItemDragListener) {
this.mData = mData;
this.mItemDragListener = mItemDragListener;
}
//recyclerview adapter 的方法 得到item布局对象
@Override
public ItemTouchHelperViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// LayoutInflater.from()像充气球一样充入一个view
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_touch_helper, parent, false);
return new ItemTouchHelperViewHolder(itemView);
}
//recyclerview adapter 的方法 绑定数据
@Override
public void onBindViewHolder(final ItemTouchHelperViewHolder holder, int position) {
holder.mTvStr.setText(mData.get(position));//TextView 绑定数据
/**
* imagview添加触摸监听,点下这个imageview执行回调,这个回调是执行
* ItemTouchHelper.startDrag(viewHolder);系统的代码 从而我们自定义的
* ItemTouchHelper.CallBack()代码,实现可拖拽效果
*/
holder.mIvDrag.setOnTouchListener(new View.OnTouchListener() {
/**
*
* @param view view添加触摸监听的view对象
*
* @param motionEvent 触摸事件
*
* MotionEvent.ACTION_DOWN 表示用户的手指刚接触到屏幕
* MotionEvent.ACTION_MOVE 表示用户的手指正在移动
* MotionEvent.ACTION_UP 表示用户的手指从屏幕上抬起
* Cancel 事件取消
*
* @return 返回值true/false
*
* 返回值为false的时候,只会执行down方法,不会执行move和up.
* 只有在true的时候,三个都会执行,可打开注释
* 注释这个mItemDragListener.onStartDrags(viewHolder);
* 看一下效果,不过可能看不太清(左右移动(上下移动被接手了)
* 最好自己写一个
*
*/
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
/**
* 执行触摸回调,这个回调方法在activity那边实现了
* (在这里实现也行,不过要改代码,这里就不示例了)
*/
mItemDragListener.onStartDrags(holder);
// switch (motionEvent.getAction()) {
// case MotionEvent.ACTION_DOWN:
// Log.e("TAG==","ACTION_DOWN");
// break;
// case MotionEvent.ACTION_MOVE:
// Log.e("TAG==","ACTION_MOVE");
// break;
// case MotionEvent.ACTION_UP:
// Log.e("TAG==","ACTION_UP");
// break;
// }
return false;
}
});
}
//实现ItemMoveListener接口的回调方法
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
//系统提供的方法 交换数据
Collections.swap(mData, fromPosition, toPosition);
//RecyclerView.Adapter刷新
notifyItemMoved(fromPosition, toPosition);
return true;
}
//实现ItemMoveListener接口的回调方法
@Override
public boolean onItemRemove(int position) {
//删除数据
mData.remove(position);
//RecyclerView.Adapter提供的 移除方法 并 刷新
notifyItemRemoved(position);
return true;
}
//recyclerview adapter 的方法 返回item条数
@Override
public int getItemCount() {
return mData.size()>0?mData.size():0;
}
//普通的 RecyclerView.ViewHolder
class ItemTouchHelperViewHolder extends RecyclerView.ViewHolder {
TextView mTvStr;
ImageView mIvDrag;
public ItemTouchHelperViewHolder(View itemView) {
super(itemView);
mTvStr = (TextView) itemView.findViewById(R.id.tvStr);
mIvDrag = (ImageView) itemView.findViewById(R.id.ivDrag);
}
}
}
4、自定义ItemTouchHelper.Callback------MyItemTouchHelperCallback.java
/**
* Created by ${chenyuexueer}
*
* 说明:自定义触摸回调
*
* 1、继承 ItemTouchHelper.Callback实现重写getMovementFlags、onMove、onSwiped这三个方法
* 2、初始化ItemMoveListener(由于ItemTouchHelperAdapter实现了这
* 个接口并实例化了方法,所以可以直接赋值,具体请自行百度)-----看 关注①
* 3、开启item长按拖拽功能
* 到了这一步已经可以实现了我们想要的,后面是实现一些动画效果等
* 4、拖拽时添加动画和视觉效果onSelectedChanged,clearView,onChildDraw
* onSelectedChanged,clearView这两个方法要一起用,否则...(你可以试着注释clearView看看)
*
*/
public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {
ItemMoveListener mItemMoveListener;
//2、初始化ItemMoveListener
public MyItemTouchHelperCallback(ItemTouchHelperAdapter mAdapter) {//构造方法,初始化数据等
mItemMoveListener = mAdapter;//初始化ItemMoveListener---------关注①
}
/**
* 1.1、重写getMovementFlags
*
* 获取动作标识
* 动作标识分:dragFlags和swipeFlags
* dragFlags:列表滚动方向的动作标识(如竖直列表就是上和下,水平列表就是左和右)
* wipeFlags:与列表滚动方向垂直的动作标识(如竖直列表就是左和右,水平列表就是上和下)
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
int flags = makeMovementFlags(dragFlags, swipeFlags);//系统方法,返回动作标记
return flags;
}
/**
*
* 1.2、onMove
*
* 当item拖拽移动时触发----执行回调
*
* @param recyclerView
* @param viewHolder 当前被拖拽的item的viewHolder
* @param target 当前被拖拽的item下方的另一个item的viewHolder,
* 这个值会跟着你拖拽的位置变化而变化,简单的说就是
* 替换到了目的viewHolder位置(不知道这么说准不准确,反正就是这个意思)
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Log.e("TAG","当前拖拽的viewholder=="+viewHolder+"拖到了这个位置的target=="+target);
return mItemMoveListener.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
}
/**
* 1.3、onSwiped
*
* 当item侧滑出去时触发(竖直列表是侧滑,水平列表是竖滑)
*
* @param viewHolder
* @param direction 滑动的方向
* 可以打开注释看一下效果,不过这里只能看到向左右的情况,
* 要看上下的自己写代码实现哈!!
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
//1--UP 2--DOWN 4--LEFT 8--RIGHT
// Log.e("TAG","滑动的方向数字值=="+direction);
// switch (direction){
// case 1:
// Log.e("TAG","滑动的方向=="+direction+"--UP向上");
// break;
// case 2:
// Log.e("TAG","滑动的方向=="+direction+"--DOWN向下");
// break;
// case 4:
// Log.e("TAG","滑动的方向=="+direction+"--LEFT向左");
// break;
// case 8:
// Log.e("TAG","滑动的方向=="+direction+"--RIGHT向右");
// break;
// }
mItemMoveListener.onItemRemove(viewHolder.getAdapterPosition());
}
/**
* 是否开启item长按拖拽功能
*/
@Override
public boolean isLongPressDragEnabled() {
return true;
}
//=====================下面是实现动画视觉效果等=============
/**
* 当item被拖拽或侧滑时触发,背景颜色变灰
*
* @param viewHolder
* @param actionState 当前item的状态
*/
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
//不管是拖拽或是侧滑,背景色都要变化
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE)
viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(android.R.color.darker_gray));
}
/**
* 当item的交互动画结束时触发,背景颜色变回白色
*
* @param recyclerView
* @param viewHolder
*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(android.R.color.white));
viewHolder.itemView.setAlpha(1);
viewHolder.itemView.setScaleY(1);
}
/**
* 侧滑时触发,视觉效果----item像是被压扁的视觉效果
*
* @param c
* @param recyclerView
* @param viewHolder
* @param dX
* @param dY
* @param actionState
* @param isCurrentlyActive
*/
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
float value = 1 - Math.abs(dX) / viewHolder.itemView.getWidth();
viewHolder.itemView.setAlpha(value);
viewHolder.itemView.setScaleY(value);
}
}
}
5.1、ItemMoveListener自定义接口
/**
* Created by ${chenyuexueer}
*
* 说明:整个item条目的触摸监听回调
*/
public interface ItemMoveListener {
//整个item条目的触摸移动事件回调,主要是用于 交换数据 、 刷新数据
boolean onItemMove(int fromPosition, int toPosition);
//整个item条目的触摸删除事件回调,主要是用于 刷新数据
boolean onItemRemove(int position);
}
5.2、ItemDragListener自定义接口
/**
* Created by ${chenyuexueer}
*
* 说明:imageview的触摸回调,按下imageview,实现拖拽功能
* 接口回调,只是示例,可以不要这个功能
*/
public interface ItemDragListener {
//按下回调
void onStartDrags(RecyclerView.ViewHolder viewHolder);
}
6、数据Cheeses.java----NAMES[]
/**
* Created by ${chenyuexueer} on 2018/5/9.
* 说明:姓名数据
*/
public class Cheeses {
public static final String[] NAMES = new String[] { "宋江", "卢俊义", "吴用",
"公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深",
"武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘",
"雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍",
" 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪",
"魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方",
"郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充",
"李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿",
"陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩",
"周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立",
"李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜",
"时迁", "段景柱" };
}
示例1.gif
额外示例 可以结合Decoration实现各种效果,其一比如下图
(效果不太友好,算是bug吗,有待优化,这里只是示例)
实现上图效果,代码如下:
①、把上面的MainActivity.java中的 注释 初始化修饰布局(首字母提示)方法打开注释,算了,我还是把代码全部贴上吧
②、结合RecyclerView.ItemDecoration
1.1、MainActivity.java
public class MainActivity extends AppCompatActivity implements ItemDragListener {
private List<String> mData = new ArrayList<>();
private RecyclerView mRv;
private ItemTouchHelperAdapter mAdapter;//adapter
private MyItemTouchHelperCallback mCallback;//自定义触摸回调
private ItemTouchHelper mItemTouchHelper;//系统的
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRv = (RecyclerView) findViewById(R.id.rv);
initData();
initDecoration();//初始化修饰布局(首字母提示)
initRecyclerView();
}
//初始化修饰布局(首字母提示),效果不友好所以注释了,没有加pinyin4j包就不要打开注释
//如果要打开就加这段依赖compile 'com.github.open-android:pinyin4j:2.5.0'
private void initDecoration() {
MyDecorationThree decorationThree = new MyDecorationThree(this, mData);
mRv.addItemDecoration(decorationThree);
}
//初始化数据
private void initData() {
for (int i = 0; i < Cheeses.NAMES.length; i++) {
mData.add(Cheeses.NAMES[i]);
}
}
//初始化recyclerview,关联adapter
private void initRecyclerView() {
//普通的 recyclerview与adapter关联
//因为mainactivity实现了ItemDragListener接口,所以可以传this,代表ItemDragListener
mAdapter = new ItemTouchHelperAdapter(mData,this);
mRv.setLayoutManager(new LinearLayoutManager(this));
mRv.setAdapter(mAdapter);
//给recyclerview.adapter设置触摸回调ItemTouchHelper.Callback
// (这个是我们自定义的MyItemTouchHelperCallback)
mCallback = new MyItemTouchHelperCallback(mAdapter);
mItemTouchHelper = new ItemTouchHelper(mCallback);
mItemTouchHelper.attachToRecyclerView(mRv);//绑定触摸回调
}
/**
* imageview的触摸回调
*
* 示例:ItemTouchHelper.startDrag() 只是示例,不要可去除这个方法
* 功能: 按下imageview就可以实现拖拽功能
* 说明:实现这个回调方法----执行ItemTouchHelper.startDrag()---就会
* 执行ItemTouchHelper.Callback----就会执行我们自定义的MyItemTouchHelperCallback)
*
* @param viewHolder
*/
@Override
public void onStartDrags(RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);//系统方法ItemTouchHelper.startDrag()
}
}
1.2、MyDecorationThree.java
public class MyDecorationThree extends RecyclerView.ItemDecoration {
Context mContext;
List<String> mData;
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//画笔
public MyDecorationThree(Context context, List<String> data) {
mContext = context;
mData = data;
//画笔字体大小与颜色
paint.setTextSize(sp2px(16));
paint.setColor(Color.RED);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
drawLetterToItemLeft(c, parent);
}
/**
* 绘制方法
* @param c 画布
* @param parent RecyclerView
*/
private void drawLetterToItemLeft(Canvas c, RecyclerView parent) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
if (!(layoutManager instanceof LinearLayoutManager)){
return;
}
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
int position = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition() + i;
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
float left = 0;
float top = child.getTop() - params.topMargin;
float right = child.getLeft() - params.leftMargin;
float bottom = child.getBottom() + params.bottomMargin;
float width = right - left;
float height = bottom - (bottom - top) / 2;
//当前名字拼音的第一个字母
String letter = PinyinUtils.getPinyin(mData.get(position)).charAt(0) + "";
if (position == 0) {
drawLetter(letter, width, height, c, parent);
} else {
String preLetter = PinyinUtils.getPinyin(mData.get(position - 1)).charAt(0) + "";
if (!letter.equalsIgnoreCase(preLetter)) {
drawLetter(letter, width, height, c, parent);
}
}
}
}
private void drawLetter(String letter, float width, float height, Canvas c, RecyclerView parent) {
float fontLength = getFontLength(paint, letter);
float fontHeight = getFontHeight(paint);
float tx = (width - fontLength) / 2;
float ty = height - fontHeight / 2 + getFontLeading(paint);
c.drawText(letter, tx, ty, paint);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
outRect.set(dip2px(40), 0, 0, 0);
}
private int dip2px(int dip) {
float density = mContext.getResources().getDisplayMetrics().density;
int px = (int) (dip * density + 0.5f);
return px;
}
public int sp2px(int sp) {
return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, mContext.getResources().getDisplayMetrics()) + 0.5f);
}
/**
* 返回指定笔和指定字符串的长度
*/
private float getFontLength(Paint paint, String str) {
return paint.measureText(str);
}
/**
* 返回指定笔的文字高度
*/
private float getFontHeight(Paint paint) {
Paint.FontMetrics fm = paint.getFontMetrics();
return fm.descent - fm.ascent;
}
/**
* 返回指定笔离文字顶部的基准距离
*/
private float getFontLeading(Paint paint) {
Paint.FontMetrics fm = paint.getFontMetrics();
return fm.leading - fm.ascent;
}
}
1.3、PinyinUtils.java
/**
* Created by ${chenyuexueer}
*
* 说明:拼音工具(需要依赖或者导入pinyin4j-2.5.0.jar)
*/
public class PinyinUtils {
/**
* 根据传入的字符串(包含汉字),得到拼音
* 如:
*
* 好学 -> HAOXUE
* 好 学*& -> HAOXUE
* 好学y2 -> HAOXUE
*
* @param str 字符串
* @return
*/
public static String getPinyin(String str) {
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.UPPERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
StringBuilder sb = new StringBuilder();
char[] charArray = str.toCharArray();
for (int i = 0; i < charArray.length; i++) {
char c = charArray[i];
// 如果是空格, 跳过
if (Character.isWhitespace(c)) {
continue;
}
if (c >= -127 && c < 128 || !(c >= 0x4E00 && c <= 0x9FA5)) {
// 满足条件 ,则肯定不是汉字
sb.append(c);
} else {
String s = "";
try {
// 通过char得到拼音集合. 单 -> dan, shan
s = PinyinHelper.toHanyuPinyinStringArray(c, format)[0];
sb.append(s);
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
sb.append(s);
}
}
}
return sb.toString();
}
}
如果缺代码就从一、(1-6)找,不确定全部文件有没有贴上,没检查(懒癌晚期)
二、TextInputLayout 简单使用
1、MainActivity.java
public class MainActivity extends AppCompatActivity {
private TextInputLayout mTextInputLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextInputLayout = (TextInputLayout) findViewById(R.id.textInputLayout);
//开启计数
mTextInputLayout.setCounterEnabled(true);
//最大长度6个
mTextInputLayout.setCounterMaxLength(6);
//定义错误提示
mTextInputLayout.getEditText().addTextChangedListener(new MyTextWatch(mTextInputLayout, "长度不能超过6个字符"));
}
class MyTextWatch implements TextWatcher {
TextInputLayout mTextInputLayout;
String mErrorTip;
public MyTextWatch(TextInputLayout textInputLayout, String errorTip) {
mTextInputLayout = textInputLayout;
mErrorTip = errorTip;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (mTextInputLayout.getEditText().getText().toString().trim().length() > 6) {
mTextInputLayout.setErrorEnabled(true);
mTextInputLayout.setError(mErrorTip);
} else {
mTextInputLayout.setErrorEnabled(false);
}
}
}
}
2、activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:id="@+id/textInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true"
app:hintAnimationEnabled="true"
app:hintEnabled="false">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintAnimationEnabled="true"
app:passwordToggleDrawable="@mipmap/ic_launcher"
app:passwordToggleEnabled="true"
app:passwordToggleTint="@color/colorPrimary">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码"
android:inputType="textPassword"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
三、ToolBar 的简单使用
image.pngToolBar 可以做很多内容,这里只记录SearchView的简单使用
3.1、SearchView
- 使用过程中遇到错误:
Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.- 描述:
由于Activity已存在ActionBar,所以使用Toolbar进行替换时出错.你可以换主题也可以增加values/styles的 资源文件- 解决方案:http://blog.csdn.net/zhaokaiqiang1992/article/details/47442691
3.1.1、MainActivity.java
public class MainActivity extends AppCompatActivity {
private Toolbar mToolbar;
private SearchView mSearchView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_view, menu);
MenuItem item = menu.findItem(R.id.menu_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(item);
/*------------------ SearchView有三种默认展开搜索框的设置方式,区别如下: ------------------*/
//设置搜索框直接展开显示。左侧有放大镜(在搜索框中) 右侧有叉叉 可以关闭搜索框
mSearchView.setIconified(false);
//设置搜索框直接展开显示。左侧有放大镜(在搜索框外) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
mSearchView.setIconifiedByDefault(false);
//设置搜索框直接展开显示。左侧有无放大镜(在搜索框中) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
mSearchView.onActionViewExpanded();
//设置最大宽度
// mSearchView.setMaxWidth(500);
//设置是否显示搜索框展开时的提交按钮
// mSearchView.setSubmitButtonEnabled(true);
//设置输入框提示语
mSearchView.setQueryHint("hint");
//搜索框展开时后面叉叉按钮的点击事件
mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
Toast.makeText(getApplicationContext(), "Close", Toast.LENGTH_SHORT).show();
return false;
}
});
//搜索图标按钮(打开搜索框的按钮)的点击事件
mSearchView.setOnSearchClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "Open", Toast.LENGTH_SHORT).show();
}
});
//搜索框文字变化监听
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
Log.e("CSDN_LQR", "TextSubmit : " + s);
return false;
}
@Override
public boolean onQueryTextChange(String s) {
Log.e("CSDN_LQR", "TextChange --> " + s);
return false;
}
});
// mSearchView.setSuggestionsAdapter();
return super.onCreateOptionsMenu(menu);
}
//右上角的MenuItem的选择事件
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.e("TAG==",item.getTitle().toString());
return super.onOptionsItemSelected(item);
}
}
3.1.2、activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:navigationIcon="@mipmap/ic_launcher"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:title="title"
app:titleTextColor="@android:color/white"/>
</LinearLayout>
3.1.3、search_view.xml 资源文件res/menu/search_view.xml
<?xml version="1.0" encoding="utf-8"?>
<menu 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">
<item
android:id="@+id/menu_search"
android:orderInCategory="100"
android:title="搜索"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"
/>
<item
android:id="@+id/scan_local_music"
android:icon="@mipmap/ic_launcher"
android:orderInCategory="100"
android:title="扫描本地音乐"
app:showAsAction="never"
/>
<item
android:id="@+id/select_sort_way"
android:icon="@mipmap/ic_launcher_round"
android:orderInCategory="100"
android:title="选择排序方式"
app:showAsAction="never"
/>
<item
android:id="@+id/get_cover_lyrics"
android:icon="@mipmap/ic_launcher"
android:orderInCategory="100"
android:title="获取封面歌词"
app:showAsAction="never"
/>
<item
android:id="@+id/imporve_tone_quality"
android:icon="@mipmap/ic_launcher_round"
android:orderInCategory="100"
android:title="升级音质"
app:showAsAction="never"
/>
</menu>
SearchView.gif
3.2、SearchView仿网易云本地音乐搜索
3.2.1、MainActivity.java
public class MainActivity extends AppCompatActivity {
private ListView mLv;
private SearchView mSearchView;
private SearchView.SearchAutoComplete mSearchAutoComplete;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
//将setSupportActionBar(toolbar)放在setNavigationOnClickListener()之前设置才行
setSupportActionBar(toolbar);
//相当于返回键的监听
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mSearchAutoComplete.isShown()) {
try {
mSearchAutoComplete.setText("");
//①、利用反射方式,调用收起SearchView的onCloseClicked()方法
Method method = mSearchView.getClass().getDeclaredMethod("onCloseClicked");
method.setAccessible(true);
method.invoke(mSearchView);
//②、或者mSearchView.setIconified(true)直接调用onCloseClicked()方法,可自行测试看效果
} catch (Exception e) {
e.printStackTrace();
}
} else {
finish();
}
}
});
mLv = (ListView) findViewById(R.id.lv);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_view, menu);//给右上角的MenuItem充入布局菜单
MenuItem searchItem = menu.findItem(R.id.menu_search);//得到一个MenuItem对象
//通过MenuItem得到SearchView
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
//相当于输入框(不知这样说准不准确)
mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);
mSearchView.setQueryHint("搜索本地歌曲by code");
//设置输入框提示文字样式
mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.darker_gray));
mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.background_light));
mSearchAutoComplete.setTextSize(14);
//设置触发查询的最少字符数(默认2个字符才会触发查询)
mSearchAutoComplete.setThreshold(1);
//设置搜索框有字时显示叉叉,无字时隐藏叉叉
mSearchView.onActionViewExpanded();
//是否展开状态,也就是是否可以输入编辑
mSearchView.setIconified(true);
//放大镜 默认为true在框内,设置false则在框外
// mSearchView.setIconifiedByDefault(false);
//是否显示提交按钮,就是有一个向右的三角形
// 设置默认无内容时的文字提示
// mSearchView.setQueryHint("情输入歌曲名查找");
//设置输入框提示文字样式
// mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.white));//设置提示文字颜色
// mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.white));//设置内容文字颜色
//修改搜索框控件间的间隔(这样只是为了更加接近网易云音乐的搜索框)
// 还有一种方式,res/style里面,请看activity_main.xml
LinearLayout search_edit_frame = (LinearLayout) mSearchView.findViewById(R.id.search_edit_frame);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) search_edit_frame.getLayoutParams();
params.leftMargin = 0;
params.rightMargin = 0;
search_edit_frame.setLayoutParams(params);
//监听SearchView的内容 ,提交按钮的事件监听
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
//提交按钮的点击事件
@Override
public boolean onQueryTextSubmit(String s) {
return false;
}
//当输入框内容改变的时候回调
@Override
public boolean onQueryTextChange(String s) {
Cursor cursor = TextUtils.isEmpty(s) ? null : queryData(s);
// if (mSearchView.getSuggestionsAdapter() == null) {
// mSearchView.setSuggestionsAdapter(new SimpleCursorAdapter(SearchViewActivity2.this, R.layout.item_layout, cursor, new String[]{"name"}, new int[]{R.id.text1}));
// } else {
// mSearchView.getSuggestionsAdapter().changeCursor(cursor);
// }
setAdapter(cursor);
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
// 让菜单同时显示图标和文字
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
if (menu != null) {
if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
try {
//①、反射方式
Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
method.setAccessible(true);
method.invoke(menu, true);
//②、。。。
} catch (Exception e) {
e.printStackTrace();
}
}
}
return super.onMenuOpened(featureId, menu);
}
//数据库查询
private Cursor queryData(String key) {
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(getFilesDir() + "music.db", null);
Cursor cursor = null;
try {
String querySql = "select * from tb_music where name like '%" + key + "%'";
cursor = db.rawQuery(querySql, null);
Log.e("CSDN_LQR", "querySql = " + querySql);
} catch (Exception e) {
e.printStackTrace();
String createSql = "create table tb_music (_id integer primary key autoincrement,name varchar(100))";
db.execSQL(createSql);
String insertSql = "insert into tb_music values (null,?)";
for (int i = 0; i < Cheeses.NAMES.length; i++) {
db.execSQL(insertSql, new String[]{Cheeses.NAMES[i]});
}
String querySql = "select * from tb_music where name like '%" + key + "%'";
cursor = db.rawQuery(querySql, null);
Log.e("CSDN_LQR", "createSql = " + createSql);
Log.e("CSDN_LQR", "querySql = " + querySql);
}
return cursor;
}
//listview的adapter
private void setAdapter(Cursor cursor) {
if (mLv.getAdapter() == null) {
SimpleCursorAdapter adapter = new SimpleCursorAdapter(MainActivity.this, R.layout.item_layout, cursor, new String[]{"name"}, new int[]{R.id.text1});
mLv.setAdapter(adapter);
} else {
((SimpleCursorAdapter) mLv.getAdapter()).changeCursor(cursor);
}
}
}
3.2.2、activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:navigationIcon="@mipmap/ic_launcher"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:title="本地音乐"
app:titleTextColor="@android:color/white"/>
<!--当ScrollView内容不足的时候,设置其height="match_parent"属性,结果还是wrap_content。使用android:fillViewport="true"-->
<!--NavigationIcon和标题之间的距离-->
<!--在res/style.xml,写入下面代码,可修改navigationIcon和SearchView之间的距离过大-->
<!--<style name="ToolbarStyle" parent="Base.Widget.AppCompat.Toolbar">-->
<!--<item name="contentInsetStart">0dp</item>-->
<!--<item name="contentInsetStartWithNavigation">0dp</item>-->
<!--</style>-->
<!---->
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@android:color/black"
android:dividerHeight="1dp"></ListView>
</LinearLayout>
3.2.3、search_view.xml
同上----3.1.3、search_view.xml 资源文件res/menu/search_view.xml
3.2.4、Adapter的item布局item_layout.xml
<?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">
<!--android:id="@android:id/text1"-->
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textColor="@android:color/black"/>
</LinearLayout>
3.2.5、数据Cheeses.NAMES [ ]
/**
* Created by ${chenyuexueer}
* 说明:数据
*/
public class Cheeses {
public static final String[] NAMES = new String[] { "宋江", "卢俊义", "吴用",
"公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深",
"武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘",
"雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍",
" 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪",
"魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方",
"郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充",
"李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿",
"陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩",
"周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立",
"李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜",
"时迁", "段景柱" };
}
SearchView仿网易云音乐搜索.gif
四、Palette 的简单使用
image.png暂时不记录在笔记中,以后有空记得就补上
五、CardView卡片效果
暂时不记录在笔记中,以后有空记得就补上
六、FloatingActionButton浮动效果
暂时不记录在笔记中,以后有空记得就补上