仿扇贝单词----自定义可拖拽控件
来源:互联网 发布:淘宝创意礼物知乎 编辑:程序博客网 时间:2024/04/30 06:11
仿扇贝单词—-自定义可拖拽控件
最近在做项目时需要实现一个可以拖动的控件,用于在有限的屏幕内显示更多的内容.先给大家看一下效果图.
这个效果的主要特点有以下几点:
1.只有按住拖拽的按钮时才可以拖动,下面的内容布局无法拖动.
2.内容布局的触摸事件处理.判断当前的点击位置是否在拖拽控件内,如果在则消耗掉该事件,反之则传递到内部.
1.首先是布局
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:id="@+id/rl_content" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="match_parent" android:text="button"/> </RelativeLayout> <com.iyuba.myapplication.view.DragView android:id="@+id/dgview" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/iv_drag" android:layout_width="wrap_content" android:layout_height="40dp" android:src="@mipmap/ic_drag_handle_black_24dp" /> <RelativeLayout android:id="@+id/rl" android:background="#009688" android:layout_width="match_parent" android:layout_height="match_parent"> </RelativeLayout> </com.iyuba.myapplication.view.DragView></FrameLayout>
这里根布局使用Fragment,自定义的DragView 在最上层.DragView 中的布局有两个子View,一个是拖拽按钮,一个是用于放置内容的布局.布局还是比较清晰的.
2.自定义的DragView
package com.iyuba.myapplication.view;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.ViewGroup;import android.widget.Scroller;/** * Author:Howard on 2016/6/3 10:00 * Email:Howard9891@163.com */public class DragView extends ViewGroup { //子view初始高度 private int mTop = 400; //拖拽按钮 private View iv_drag; //容器 private View contentView; private int lastY; private int lastX; private Context mContext; private int dy; //存放view 在屏幕中的坐标 private int[] viewLocation; //存放父view 在屏幕中的坐标 private int[] parentLocation; //记录按下时的X坐标 private int mInitialMotionX; //记录按下时的Y坐标 private int mInitialMotionY; //Scrllor 帮助类 private Scroller mScroller; //设置滑动偏差值 private int touchSlop =20; //父view 高度 private int mHeight; //拖拽按钮高度 private int ivHeight; //获取滑动速度的帮助类 private VelocityTracker mVelocityTracker; public DragView(Context context) { this(context,null); } public DragView(Context context, AttributeSet attrs) { this(context, attrs,0); } public DragView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.mContext = context; init(); } private void init() { mScroller = new Scroller(mContext); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measureWidth = MeasureSpec.getSize(widthMeasureSpec); int measureHeight = MeasureSpec.getSize(heightMeasureSpec); //测量子类 for(int i=0;i<getChildCount();i++){ View child =getChildAt(i); child.measure(measureWidth,measureHeight); } setMeasuredDimension(measureWidth,measureHeight); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { //设置每个子View 在父view中的位置 iv_drag = getChildAt(0); contentView = getChildAt(1); iv_drag.layout(0,mTop,r,mTop+ iv_drag.getMeasuredHeight()); contentView.layout(0,mTop+iv_drag.getMeasuredHeight(),r,mTop+this.getHeight()); Log.e("DragView","height>>>"+this.getMeasuredHeight()); mHeight =this.getMeasuredHeight(); ivHeight = iv_drag.getMeasuredHeight(); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); obtainVelocity(event); switch (action){ case MotionEvent.ACTION_DOWN: obtainVelocity(event); Log.e("DragView","down"); mInitialMotionX= lastX = (int) event.getX(); mInitialMotionY= lastY = (int) event.getY(); Log.e("DragView","lastY:>>>"+lastY); break; case MotionEvent.ACTION_MOVE: Log.e("DragView","move"); getVelocity(); dy = (int)event.getY()-lastY; //判断用户是否按住拖拽按钮,并获得当前滑动速度 // 平稳滑动 if(isViewHit(iv_drag,lastX,lastY)&&Math.abs(getVelocity())<2000){ //滑动到最顶端,禁止在往上滑动 if(viewLocation[1]<parentLocation[1]&&dy<0){ break; } //滑动到最底端,禁止往下滑动 if(viewLocation[1]-parentLocation[1]>=mHeight-ivHeight&&dy>0){ break; } scrollBy(0,-dy); lastY = (int) event.getY(); lastX = (int) event.getX(); }////判断用户是否按住拖拽按钮,并获得当前滑动速度 // 快速滑动 else if(isViewHit(iv_drag,lastX,lastY)&&Math.abs(getVelocity())>=2000){ if(dy<0){ mScroller.startScroll(0,getScrollY(),0,mTop-getScrollY()); postInvalidate(); } } break; case MotionEvent.ACTION_UP: //当前是按住按钮不动,松开后,View滑到最低部 if(Math.abs(event.getX()-mInitialMotionX)<touchSlop &&Math.abs(event.getY()-mInitialMotionY)<touchSlop &&isViewHit(iv_drag,(int)event.getX(),(int)event.getY())){ mScroller.startScroll(0,getScrollY(),0,ivHeight-mHeight+mTop-getScrollY(),1000); postInvalidate(); }//边界处理,滑到超过顶部,滚到顶部 if(viewLocation[1]<parentLocation[1]){ mScroller.startScroll(0,getScrollY(),0,viewLocation[1]-parentLocation[1]); postInvalidate(); }//边界处理,滑到超过底部,滚到底部 if(viewLocation[1]-parentLocation[1]>=mHeight-ivHeight){ mScroller.startScroll(0,getScrollY(),0,(viewLocation[1]-parentLocation[1]-mHeight+ivHeight)); postInvalidate(); } Log.e("DragView","viewPosition[1]"+viewLocation[1]); Log.e("DragView","up"); recycleVelocity(); break; case MotionEvent.ACTION_CANCEL: recycleVelocity(); break; } return isViewHit(iv_drag,lastX,lastY)||isViewHit(contentView,lastX,lastY); } /** *用于判断传入的x,y 坐标是否在view 范围内. * */ public boolean isViewHit(View view,int x,int y){ viewLocation = new int[2]; view.getLocationInWindow(viewLocation); parentLocation = new int[2]; this.getLocationInWindow(parentLocation); int screenX = parentLocation[0] + x; int screenY = parentLocation[1] + y; return screenX > viewLocation[0]&&screenX< viewLocation[0]+view.getWidth()&& screenY > viewLocation[1]&&screenY< viewLocation[1]+view.getHeight(); } /** * 获取y方向的加速度 * * @return */ private int getVelocity() { mVelocityTracker.computeCurrentVelocity(1000); return (int) mVelocityTracker.getYVelocity(); } /** * 释放资源 */ private void recycleVelocity() { if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } } private void obtainVelocity(MotionEvent event) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); } @Override public void computeScroll() { Log.e("DragView","computeScroll"); super.computeScroll(); if(mScroller.computeScrollOffset()){ Log.e("DragView1","mScroller.getCurrY()"+mScroller.getCurrY()); scrollTo(0,mScroller.getCurrY()); postInvalidate(); } }}
里面有很多高度的计算,大家在草稿纸上画一下就清楚了.
1 0
- 仿扇贝单词----自定义可拖拽控件
- 采集文献不认识单词上传扇贝网
- [python爬虫]模拟登陆扇贝单词
- 让扇贝单词书中的单词可以发音
- 【扇贝批量添加单词到词库】利用python调用扇贝API (oauth2)
- 自定义可拖拽显示数字BadgeView(仿QQ可拖拽控件)
- 仿QQ slidingmenu 自定义属性 自定义控件
- 今日扇贝英语学习难记单词继续努力
- Android 自定义控件-SnakeLayout (仿gallery)
- Android 自定义控件 仿乐Phone UI
- Android 自定义控件-SnakeLayout (仿gallery)
- 自定义控件--仿QQ表情面板
- 自定义控件省市区:仿苹果级联菜单
- 自定义控件之仿IOS的ToggleButton
- 自定义控件之仿IOS的ToggleButton
- Android 自定义日期控件 (仿QQ,IOS7)
- 自定义控件-仿iphone之ToggleButton&VoiceSeekBar
- Android自定义控件--仿 path 效果 ArcMenu
- 解析XML的 - dom4j 和 jdom
- SVN中trunk,branches,tags用法详解
- quartz spring 实现动态定时任务
- SOCKET JAVA CTISERVER
- Android 日期控件只显示年月
- 仿扇贝单词----自定义可拖拽控件
- C#中byte与short、int、long互相转化
- 如何使用Android Studio开发/调试Android源码
- 策略管理
- Android利用canvas画各种图形(点、直线、弧、圆、椭圆、文字、矩形、多边形、曲线、圆角矩形)
- 安卓App热补丁动态修复技术介绍
- Android 屏幕适配的一种方案
- npm
- iOS学习项目(08-UITableView)