高级UI-自定义控件
自定义控件在Android开发中有着大量的运用,为了做出符合项目的效果很多时候需要自定义控件,这里就使用两个自定义控件,来说明自定义控件的使用流程
仿QQ侧滑
之前使用DrawerLayout和NavigationView都实现了侧滑的效果,在这里使用自定义的View完成相同的效果
这里考虑到的是继承HorizontalScrollView,复写里面的onMeasure方法,设置滑动菜单和主菜单的宽度设置,复写onLayout方法,按照需求摆放子控件,复写onTouchEvent方法,控制移动距离,复写onScrollChanged方法,控制滑动时候的动画
布局
<?xml version="1.0" encoding="utf-8"?>
<com.cj5785.customviewtest.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_light"
android:scrollbars="none">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@android:color/holo_green_light"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@android:color/darker_gray"/>
</LinearLayout>
</com.cj5785.customviewtest.SlidingMenu>
自定义控件
public class SlidingMenu extends HorizontalScrollView {
private int mScreenWidth;
private ViewGroup mMenu;
private ViewGroup mMain;
private int mMenuWidth;
private boolean isOnce;
private float downX;
public SlidingMenu(Context context, AttributeSet attrs) {
super(context, attrs);
//得到屏幕宽度
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
mScreenWidth = metrics.widthPixels;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//只测量一次
if (!isOnce) {
//获得侧滑菜单和主菜单
LinearLayout wrapper = (LinearLayout) getChildAt(0);
mMenu = (ViewGroup) wrapper.getChildAt(0);
mMain = (ViewGroup) wrapper.getChildAt(1);
//得到宽度,为了体验效果,这里一般会设置menu的right padding宽度
mMenuWidth = mScreenWidth - mScreenWidth / 5;
mMenu.getLayoutParams().width = mMenuWidth;
mMain.getLayoutParams().width = mScreenWidth;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed) {
//开始绘制的时候,向右滑动一段距离
this.scrollTo(mMenuWidth, 0);
isOnce = true;
}
super.onLayout(changed, l, t, r, b);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
//按下时的位置
downX = ev.getX();
break;
case MotionEvent.ACTION_UP:
//松开后滑动的距离,滑动距离小于屏幕的四分之一则回到原位置
float dx = ev.getX() - downX;
if (dx < mScreenWidth / 4) {
this.smoothScrollTo(mMenuWidth, 0);
} else {
this.smoothScrollTo(0, 0);
}
return true;
}
return super.onTouchEvent(ev);
}
//当滑动开始时候会调用onScrollChanged()
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
//在这里设置动画
//滑动百分比
float factor = (float) l / mMenuWidth;
//1.平移效果
mMenu.setTranslationX(mMenuWidth * factor * 0.7F);
//2.缩放效果
mMenu.setScaleX(1 - 0.4F * factor);
mMenu.setScaleY(1 - 0.4F * factor);
mMain.setScaleX(0.9F + 0.1F * factor);
mMain.setScaleY(0.9F + 0.1F * factor);
//3.透明度效果
mMenu.setAlpha(1 - factor);
mMain.setAlpha(0.8F + 0.2F * factor);
super.onScrollChanged(l, t, oldl, oldt);
}
}
实现效果如下

实现条目侧滑的效果
在QQ中,还有个功能是比较棒的,那就是条目侧滑,那么要怎么实现条目侧滑效果呢
这里我们使用自定义LinearLayout来实现,其滑动效果通过Scroller来控制
使用dispatchTouchEvent()来记录DOWN,MOVE,UP事件响应的参数,滑动过程中不断调用computeScroll()移动控件位置,使得其形成动画效果,由于要控制滑动距离,就需要动态测量出滑出的距离,复写onFinishInflate()得到距离
布局很简单,就是两个TextView
<?xml version="1.0" encoding="utf-8"?>
<com.cj5785.customviewtest.SlidingItemMenuLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="@android:color/holo_green_light"
android:gravity="center"
android:text="This is a item"
android:textSize="32sp" />
<TextView
android:layout_width="100dp"
android:layout_height="80dp"
android:background="@android:color/holo_red_light"
android:gravity="center"
android:text="删除"
android:textSize="32sp" />
</com.cj5785.customviewtest.SlidingItemMenuLayout>
然后是自定义控件
public class SlidingItemMenuLayout extends LinearLayout {
private Scroller mScroller;
private float startX;
private float startY;
private float dx;
private float dy;
private View rightChild;
public SlidingItemMenuLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.HORIZONTAL);
//用来设置松开回弹
mScroller = new Scroller(getContext(), new AccelerateInterpolator(), true);
}
//绘制完成后调用
@Override
protected void onFinishInflate() {
super.onFinishInflate();
rightChild = getChildAt(1);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//记录按下时位置
startX = ev.getX();
startY = ev.getY();
//按下以后拦截事件,交由父类处理
super.dispatchTouchEvent(ev);
return true;
case MotionEvent.ACTION_MOVE:
dx = ev.getX() - startX;
dy = ev.getY() - startY;
//系统能检测到的最小距离
if (Math.abs(dx) - Math.abs(dy) > ViewConfiguration.getTouchSlop()) {
//向左滑动距离不能大于最右边,且向右滑动距离不能大于零
if (getScrollX() + (-dx) > rightChild.getWidth()
|| getScrollX() + (-dx) < 0) {
return true;
}
//滑动一段距离,重新记录位置,拦截滑动事件
scrollBy((int) -dx, 0);
startX = ev.getX();
startY = ev.getY();
return true;
}
break;
case MotionEvent.ACTION_UP:
//得到松手时的偏移量,超过一半则全部显示,否则不显示
int offset = getScrollX() / (float) rightChild.getWidth() > 0.5 ?
rightChild.getWidth() - getScrollX() : -getScrollX();
//初始化滑动参数
mScroller.startScroll(getScrollX(), getScrollY(), offset, 0);
//重新绘制测量,此时会调用computeScroll()方法
invalidate();
//参数重新赋值
startX = 0;
startY = 0;
dx = 0;
dy = 0;
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
//开启滑动以后,就会不断调用此方法
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
super.computeScroll();
}
}
实现效果如下

高级UI-自定义控件的更多相关文章
- firefox 扩展开发笔记(三):高级ui交互编程
firefox 扩展开发笔记(三):高级ui交互编程 前言 前两篇链接 1:firefox 扩展开发笔记(一):jpm 使用实践以及调试 2:firefox 扩展开发笔记(二):进阶开发之移动设备模拟 ...
- Android 高级UI设计笔记07:RecyclerView 的详解
1. 使用RecyclerView 在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...
- iOS开发——高级UI&带你玩转UITableView
带你玩装UITableView 在实际iOS开发中UITableView是使用最多,也是最重要的一个控件,如果你不会用它,那别说什么大神了,菜鸟都不如. 其实关于UItableView事非常简单的,实 ...
- 高级UI晋升之自定义View实战(六)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从Android 自定义属性动画&Camera动画来介绍自定义V ...
- 高级UI晋升之自定义View实战(五)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从自定义View利器Canvas和Paint来进行详解 一.Canvas ...
- 高级UI晋升之布局ViewGroup(四)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从LinearLayout.RelativeLayout.FrameLa ...
- 高级UI晋升之常用View(三)中篇
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680本篇文章将从ViewPager来介绍常用View:文章目录 一.简介 二.基本使用 ...
- 高级UI晋升之View渲染机制(二)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 优化性能一般从渲染,运算与内存,电量三个方面进行,今天开始说聊一聊Android ...
- 高级UI晋升之触摸事件分发机制(一)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 0. 前言 鉴于安卓分发机制较为复杂,故分为多个层次进行讲解,分别为基础篇.实践 ...
- Android 高级UI设计笔记21:Android SegmentView(分段选择控件)
1. 分段控制(SegmentView) 首先我们先看看什么是SegmentView的效果,如下: 分段控制这个View控件是ios7的分段控制,和QQ消息页面顶部的效果一样,android没有这个控 ...
随机推荐
- 《exception》第九次团队作业:Beta冲刺与验收准备(第一天)
一.项目基本介绍 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 Exception 作业学习目标 1.掌握软件黑盒测试技术:2.学会编制软件项目 ...
- 指数基金介绍专栏(4):上证50AH优选指数
作者:牛大 | 公众号:定投五分钟 大家好,我是牛大.每天五分钟,投资你自己:坚持基金定投,终会财富自由! 想必大家会有疑问,什么是上证50AH优选指数?今天老师给大家答疑解惑,详细介绍一下上证50A ...
- Oracle 查看index是否失效
一.普通索引是否失效 select * from dba_indexes s where s.owner in ('ISMP','BOSS','PAY','ACCOUNT','SETTLE','TE ...
- 解决configure: WARNING: You will need re2c 0.13.4 or later
我在安装rabbitmq php扩展的时候发现 configure: WARNING: You will need re2c 0.13.4 or later if you want to regene ...
- c++中关于堆和堆栈的区别
在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区. 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量 的存储区.里面的变量通常是局部 ...
- mysql sin() 函数
mysql> ); +---------------------+ | sin(PI()/) | +---------------------+ | 0.49999999999999994 | ...
- 帝国cms万能标签实现标题截取后自动加入省略号的方法
很多采用帝国CMS建站的站长都会遇到标题过长导致页面排版错乱的情况,这时候往往需要用标题截取并追加上省略号的方法予以解决.对此,帝国CMS万能标签标题截取后自动加入省略号,没有达到字数的则不加省略号可 ...
- spring 整合 servlet
目的:记录spring整合 servlet过程demo.(企业实际开发中可能很少用到),融会贯通. 前言:在学习spring 过程(核心 ioc,aop,插一句 学了spring 才对这个有深刻概念, ...
- 刷题记录:[De1ctf] shell shell shell
目录 刷题记录:[De1ctf] shell shell shell 一.知识点 1.源码泄露 2.正则表达式不完善导致sql注入 3.soapclient反序列化->ssrf 4.扫描内网 5 ...
- 第10组 Alpha冲刺(6/6)
链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 tomcat的学习与实现 服务器后端部署,API接口的beta版实现 后端代码 ...