Android学习笔记,整理给自己复习的时候看的,谢谢!
- Android自身带的控件不能满足需求, 需要根据自己的需求定义控件.
自定义控件可以分为三大类型
1. 组合已有的控件实现
优酷菜单
1. 在xml布局里摆放好
2. 给指定控件添加点击事件
3. 根据业务逻辑,执行动画(旋转动画: 补间动画)
4. 菜单按钮的截获轮播图广告
1. 让图片滑动起来(ViewPager)
2. 让图片和文字,指示器对应起来
3. 让轮播器无限循环向右无限循环 0 -> 4 newPosition = position % 5 5 -> 0 6 -> 1 7 -> 2 8 -> 3 9 -> 4 10 -> 0 向左无限循环 设置到中间某个位置. 4. 轮播器自动轮询, OK
下拉选择框
Button或ImageButton等自带按钮功能的控件会抢夺所在Layout的焦点.导致其他区域点击不生效.在所在layout声明一个属性
android:descendantFocusability="blocksDescendants"
popupwindow获取焦点, 外部可点击
// 设置点击外部区域, 自动隐藏 popupWindow.setOutsideTouchable(true); // 外部可触摸 popupWindow.setBackgroundDrawable(new BitmapDrawable()); // 设置空的背景, 响应点击事件 popupWindow.setFocusable(true); //设置可获取焦点
2. 完全自定义控件.(继承View, ViewGroup)
1. 自定义开关
- 写个类继承View
- 拷贝包含包名的全路径到xml中
- 界面中找到该控件, 设置初始信息
- 根据需求绘制界面内容
- 响应用户的触摸事件
- 创建一个状态更新监听
// 1. 声明接口对象
public interface OnSwitchStateUpdateListener{
// 状态回调, 把当前状态传出去
void onStateUpdate(boolean state);
}
// 2. 添加设置接口对象的方法, 外部进行调用
public void setOnSwitchStateUpdateListener(
OnSwitchStateUpdateListener onSwitchStateUpdateListener) {
this.onSwitchStateUpdateListener = onSwitchStateUpdateListener;
}
// 3. 在合适的位置.执行接口的方法
onSwitchStateUpdateListener.onStateUpdate(state);
// 4. 界面/外部, 收到事件.
- 自定义属性
1. 在attrs.xml声明节点declare-styleable
<declare-styleable name="ToggleView">
<attr name="switch_background" format="reference" />
<attr name="slide_button" format="reference" />
<attr name="switch_state" format="boolean" />
</declare-styleable>
2. R会自动创建变量
attr 3个变量
styleable 一个int数组, 3个变量(保存位置)
3. 在xml配置声明的属性/ 注意添加命名空间
xmlns:itheima="http://schemas.android.com/apk/res/com.itheima74.toggleview"
itheima:switch_background="@drawable/switch_background"
itheima:slide_button="@drawable/slide_button"
itheima:switch_state="false"
4. 在构造函数中获取并使用
// 获取配置的自定义属性
String namespace = "http://schemas.android.com/apk/res/com.itheima74.toggleview";
int switchBackgroundResource = attrs.getAttributeResourceValue(namespace , "switch_background", -1);
- Android 的界面绘制流程
测量 摆放 绘制
measure -> layout -> draw
| | |
onMeasure -> onLayout -> onDraw 重写这些方法, 实现自定义控件
都在onResume()之后执行
View流程
onMeasure() (在这个方法里指定自己的宽高) -> onDraw() (绘制自己的内容)
ViewGroup流程
onMeasure() (指定自己的宽高, 所有子View的宽高)-> onLayout() (摆放所有子View) -> onDraw() (绘制内容)
2. 侧滑面板
- 在xml布局里摆放内容. include
- 在自定义ViewGroup里, 进行measure测量, layout布局
- 响应用户的触摸事件
- int scrollX = (int) (downX - moveX);
- getScrollX()获取当前滚动到的位置
- 平滑动画
//1. 开始模拟数据
scroller.startScroll(startX, 0, dx, 0, duration);
invalidate();// 重绘界面 -> drawChild() -> computeScroll();
//2. 在computeScroll中不断获取模拟的数值
@Override
public void computeScroll() {
super.computeScroll();
if(scroller.computeScrollOffset()){
// true, 动画还没有结束
// 获取当前模拟的数据, 也就是要滚动到的位置
int currX = scroller.getCurrX();
scrollTo(currX, 0); // 滚过去
invalidate(); // 重绘界面
}
}
3. 继承已有的控件实现(扩展已有的功能)
-
包含下拉刷新功能的ListView
添加了自定义的头布局
- 默认让头布局隐藏setPadding.设置 -自身的高度
- ListView下拉的时候, 修改paddingTop, 让头布局显示出来
触摸动态修改头布局, 根据paddingTop.
- paddingTop = 0 完全显示
- paddingTop < 不完全显示 -64(自身高度)完全隐藏
- paddingTop > 0 顶部空白
松手之后根据当前的paddingTop决定是否执行刷新
- paddingTop < 0 不完全显示, 恢复
- paddingTop >= 0 完全显示, 执行正在刷新…