热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android自定义滑块解锁,自定义滑动解锁View

先写出自定义View界面代码如下:先创建一个View继承View,然后重写测量方法去测量出要显示的真是高度,再重写绘制方法,

先写出自定义View界面

代码如下:先创建一个View继承View,然后重写测量方法去测量出要显示的真是高度,再重写绘制方法,去把这个按钮绘制在什么位置。然后就是为我们后续的触摸事件做准备,重写OnTouchEvent()

package com.example.z.selfscrollunlock;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.support.annotation.Nullable;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

/**

* Created by z on 2017/11/25.

*/

public class SelfUnLockView extends View {

private Bitmap mBitmap;

private int mHeight;

private int mWidth;

private Paint mPaint;

private int mWidth1;

public SelfUnLockView(Context context) {

this(context, null);

}

public SelfUnLockView(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_button);

mHeight = mBitmap.getHeight();

mWidth = mBitmap.getWidth();

mPaint = new Paint();

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

mWidth1 = MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.EXACTLY);

setMeasuredDimension(mWidth1, mHeight);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawBitmap(mBitmap, 0, 0, mPaint);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

float rawX = event.getRawX();

//当我手指触摸到滑块时候,滑块过来要移动这个点减去滑块一般的长度 raw

float moveX = rawX - mWidth / 2;

scrollTo((int) -moveX,0);

break;

case MotionEvent.ACTION_MOVE:

break;

case MotionEvent.ACTION_UP:

break;

}

return super.onTouchEvent(event);

}

}

在自定义View 的构造方法中,我们去初始化一个画笔,初始化背景的 长 宽。在onTouch()中,处理触摸事件,在手指按下的时候,让滑块中间位置移动到触摸点:注意,这个ScrollTo方法,往右边移动是减去一个数,可以想成,水调用这个Scroll方法,是this ,当前自定义View。你简单记忆成这个移动是移动他的爹,滑块向右移动,你就当成是滑块不动,他爹应该是往那边移动才是我们想要的结果,他爹是往左边移动才行。我们的左边是右边正,往左了肯定是负。效果如下:

但是很多问题,比如越界问题,回弹等,我们一步一步处理

处理点击滑块外部不响应

把这个滑动事件判断一下执行:

if (rawX > 0 && rawX

scrollTo((int) -moveX, 0);

}

处理左边越界问题

更改一个地方:

if (rawX > mWidth/2 && rawX

处理滑块滑动

在ontouch事件的move 动作中处理:并处理滑动越界问题

case MotionEvent.ACTION_MOVE:

//处理越界问题

float rawXMove = event.getRawX();//

if(rawXMove >mWidth/2 && rawXMove <=getMeasuredWidth()-mWidth/2){

float dexX = rawXMove - mWidth/2; //变化量

scrollTo((int) ( - dexX), 0);

}

break;

注意上面的滑动越界问题,我是通过手指的位置判断的,当然你可以通过一个增加量来判断是否满足条件,如果满足不满足条件直接把偏移量置零或者最大 。注意上面的判断有个细节,我使用的是getMeasuredWidth( ) 来处理,并不是用的mWidth1,如果你是用后者,你会发现这个值非常大。会越界。这里的getMeasuredWidth()拿的值就是控件背景宽度。如果弄不明白就直接使用增加量判断

你的滑块是否能滑动呢?

如果你的滑块能点击,不能滑动,注意看你的自定义控件是否消费事件,如果没有消费事件,就是掉super方法,肯定不会处理,所以你要返回值改为true.消费时间才行,因为滑动事件和点击事件不同的!

滑块的回原点

case MotionEvent.ACTION_UP:

float endRawX = event.getRawX();

if(endRawX

scrollTo(0,0);

}else {

Toast.makeText(getContext(),"解锁成功",Toast.LENGTH_LONG).show();

}

解锁不成功,缓慢回弹

1.创建Scroller对象

2.调用startScroll 方法去滚动 ,配置滚动信息

3.出发重新绘制调用 invalidate();

4.计算滚动的偏移量。重写computerScroll( ) ,根据当前已过时间计算偏移量 返回的是boolean值,如果没结束,就是滚动还没有结束, scroller.scrollTo(X,getcriiX(),0)然后出发绘制,完整代码如下:

package com.example.z.selfscrollunlock;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Paint;

import android.support.annotation.Nullable;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.widget.Scroller;

import android.widget.Toast;

/**

* Created by z on 2017/11/25.

*/

public class SelfUnLockView extends View {

private Bitmap mBitmap;

private int mHeight;

private int mWidth;

private Paint mPaint;

private int mWidth1;

private float mRawX;

private Scroller mScroller;

private ScrollListener mListener;

public SelfUnLockView(Context context) {

this(context, null);

}

public SelfUnLockView(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_button);

mHeight = mBitmap.getHeight();

mWidth = mBitmap.getWidth();

mPaint = new Paint();

mScroller = new Scroller(getContext());

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

mWidth1 = MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.EXACTLY);

setMeasuredDimension(mWidth1, mHeight);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawBitmap(mBitmap, 0, 0, mPaint);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

mRawX = event.getRawX();

//当我手指触摸到滑块时候,滑块过来要移动这个点减去滑块一般的长度 raw

float moveX = mRawX - mWidth / 2;

if (mRawX > mWidth / 2 && mRawX

scrollTo((int) -moveX, 0);

}

break;

case MotionEvent.ACTION_MOVE:

//处理越界问题

float rawXMove = event.getRawX();//

if(rawXMove >mWidth/2 && rawXMove <=getMeasuredWidth()-mWidth/2){

float dexX = rawXMove - mWidth/2; //变化量

scrollTo((int) ( - dexX), 0);

}

break;

case MotionEvent.ACTION_UP:

float endRawX = event.getRawX();

if(endRawX

/* mScroller.startScroll(getScrollX(),0,0-getScrollX(),0,500); //配置滚动信息

// invalidate();

// scrollTo(0,0);*/

int startX = getScrollX();//滚动开始时滚动偏移量

int startY = 0;

int endX = 0;//滚动最终位置的滚动偏移量

int dx = endX - startX;//滚动偏移量的变化量

int dy =0;

int duration = 1500;//滚动时长

//step2:配置滚动的成员变量

mScroller.startScroll(startX, startY, dx, dy, duration);

invalidate();//step3:触发重新绘制

}else {

Toast.makeText(getContext(),"解锁成功",Toast.LENGTH_LONG).show();

/** 出发接口方法*/

if(mListener != null){

mListener.onScrollunLock();

}

}

break;

}

return true;

}

@Override

public void computeScroll() {

if(mScroller.computeScrollOffset()){

scrollTo(mScroller.getCurrX(),0);

invalidate();

}

}

/**

* 回调函数

*/

public interface ScrollListener{

void onScrollunLock();

}

/**

* 宫外不调用的方法

*/

public void onScrollViewMethed(ScrollListener l){

this.mListener = l;

}

}

测滑菜单

需求分析:

1.继承Viewgroup

2.测量布局孩子

3.处理越界问题

package com.example.z.selfscrollunlock;

import android.content.Context;

import android.util.AttributeSet;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

/**

* Created by z on 2017/11/25.

*/

public class SlidingMenu extends ViewGroup {

private float mRawX;

private View mRight;

private View mLeft;

private int mMeasuredWidth;

private int mMeasuredWidth1;

public SlidingMenu(Context context) {

this(context, null);

}

public SlidingMenu(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

measureChildren(widthMeasureSpec, heightMeasureSpec);

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

mLeft = getChildAt(0);

mRight = getChildAt(1);

mMeasuredWidth = mLeft.getMeasuredWidth();

mMeasuredWidth1 = mRight.getMeasuredWidth();

int measuredHeight = mLeft.getMeasuredHeight();

int measuredHeight1 = mRight.getMeasuredHeight();

mLeft.layout(-mMeasuredWidth, 0, 0, measuredHeight);

mRight.layout(0, 0, mMeasuredWidth1, measuredHeight1);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

mRawX = event.getRawX();

break;

case MotionEvent.ACTION_MOVE:

float rawX1 = event.getRawX();

float v = -rawX1 + mRawX; //滚动偏移量

float finall = v + getScrollX(); //最终偏移量

if(finall >0){

scrollTo(0,0);

}else {

scrollTo(-mMeasuredWidth,0);

}

return true;

//

// int i = mMeasuredWidth1 - mMeasuredWidth;

// if (v

// v = i;

// }

// else if (v <-mMeasuredWidth) {

// v = 0;

// }

scrollTo((int) -v, 0);

// scrollBy((int) -v, 0);

// mRawX = rawX1;

}

return true;

}

}



推荐阅读
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • android 触屏处理流程,android触摸事件处理流程 ? FOOKWOOD「建议收藏」
    android触屏处理流程,android触摸事件处理流程?FOOKWOOD「建议收藏」最近在工作中,经常需要处理触摸事件,但是有时候会出现一些奇怪的bug,比如有时候会检测不到A ... [详细]
  • macOS命令行创建Android模拟器
    macOS下不安装AndroidStudio使用VSCode来开发Flutter应用使用命令行创建和管理Android模拟器设备avdmanageravdmanager 是一种命令 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Android源码中的Builder模式及其作用
    本文主要解释了什么是Builder模式以及其作用,并结合Android源码来分析Builder模式的实现。Builder模式是将产品的设计、表示和构建进行分离,通过引入建造者角色,简化了构建复杂产品的流程,并且使得产品的构建可以灵活适应变化。使用Builder模式可以解决开发者需要关注产品表示和构建步骤的问题,并且当构建流程发生变化时,无需修改代码即可适配新的构建流程。 ... [详细]
author-avatar
穿靴子的猫
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有