用QQ的時候,發現未讀消息拖拽效果蠻有意思,就模仿了一下。java
具體效果以下:android
效果圖具備如下特性:git
先分析這個視圖的組成:github
canvas.drawCircle
便可,定點中心圓的圓心是固定的,拖拽圓的圓形是手指觸摸屏幕的座標。那麼(p1-p3)這條線能夠用如下僞碼來繪製:canvas
Path rPathLeft = new Path();
rPathLeft.moveTo(P1.x,P1.y);
rPathLeft.quadTo(M.x,M.y,P3.x,P3.y);
複製代碼
同理(P2-P4)這條線能夠用如下僞代碼來繪製:app
Path rPathRight = new Path();
rPathRight.moveTo(P2.x,P2.y);
rPathRight.quadTo(M.x,M.y,P4.x,P4.y);
複製代碼
rPathLeft.lineTo(P4.x,P4.y)
rPathRight.lineTo(P2.x,P2.y)
複製代碼
繪製以上兩條貝塞爾曲線和直線須要五個點:P1,P2,P3,P4,M,其中P1,P2,P3,P4是圓的切點,如今只知道兩個圓的中心圓點O1和O2,那麼怎麼根據這兩個點來求其他四個圓的切點呢?先分析:ide
根據上圖可得知:函數
tan(a) = y / x佈局
a = arctan(y / x)post
P3.x = X1-r2*sina
P3.y = Y1-r2*cosa
P1.x = X0-r1*sina
P1.y = X0-r1*cosa
同理P2,P4也能夠求出。
下面先靜態實現繪製圖像,直接繼承幀佈局(FrameLayout)
public class RedPointView extends FrameLayout{
//畫筆
private Paint rPaint,tPaint;
//半徑
private int rRadius;
//固定圓的圓心
PointF tCenterPointF = new PointF(300,400);
//拖拽圓的圓心
PointF tDragPointF = new PointF(200,550);
//固定圓的半徑
private float tCenterRadius = 30;
//拖拽圓的半徑
private float tDragRadius = 30;
//線條
private Path rPath;
//一個參數的構造函數,調用兩個參數的構造函數
public RedPointView(Context context) {
this(context,null);
}
//兩個參數的構造函數,調用三個參數的構造函數
public RedPointView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
//三個參數的構造函數
public RedPointView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
//初始化小圓
private void init(){
//初始化Paint對象
rPaint = new Paint();
//設置顏色 紅色
rPaint.setColor(Color.RED);
//設置抗鋸齒
rPaint.setAntiAlias(true);
//設置填充
rPaint.setStyle(Paint.Style.FILL);
tPaint = new Paint();
//設置顏色 紅色
tPaint.setColor(Color.RED);
//設置抗鋸齒
tPaint.setAntiAlias(true);
//半徑 25
rRadius = 25;
}
//繪製本身孩子方法
//ViewGroup上繪製東西的時候每每重寫的是dispatchDraw()方法而不是onDraw()方法
protected void dispatchDraw(Canvas canvas){
super.dispatchDraw(canvas);
//先繪製固定圓
canvas.drawCircle(tCenterPointF.x,tCenterPointF.y,tCenterRadius,rPaint);
//再繪製拖拽圓
canvas.drawCircle(tDragPointF.x,tDragPointF.y,tDragRadius,rPaint);
float x = tCenterPointF.x - tDragPointF.x;
float y = tDragPointF.y - tCenterPointF.y;
//求a的角度
double a = Math.atan(y / x);
//中心圓的p1 x座標偏移
float offsetX1 = (float) (tCenterRadius * Math.sin(a));
float offsetY1= (float) (tCenterRadius * Math.cos(a));
//拖拽圓的p2 x座標偏移
float offsetX2 = (float) (tDragRadius * Math.sin(a));
float offsetY2= (float) (tDragRadius * Math.cos(a));
//p1的座標
float p1_x = tCenterPointF.x - offsetX1;
float p1_y = tCenterPointF.y - offsetY1;
//p2的座標
float p2_x = tCenterPointF.x + offsetX1;
float p2_y = tCenterPointF.y + offsetY1;
//p3的座標
float p3_x = tDragPointF.x - offsetX2;
float p3_y = tDragPointF.y - offsetY2;
//p4的座標
float p4_x = tDragPointF.x + offsetX2;
float p4_y = tDragPointF.y + offsetY2;
//控制點M的座標
float controll_x = (tCenterPointF.x + tDragPointF.x) / 2;
float controll_y = (tDragPointF.y + tCenterPointF.y) / 2;
//建立Path來繪製路徑
rPath = new Path();
//繪製路徑方向:P1->P3->P4->P1
rPath.reset();
rPath.moveTo(p1_x,p1_y);
rPath.quadTo(controll_x,controll_y,p3_x,p3_y);
rPath.lineTo(p4_x,p4_y);
rPath.quadTo(controll_x,controll_y,p2_x,p2_y);
rPath.lineTo(p1_x,p1_y);
rPath.close();
canvas.drawPath(rPath,tPaint);
}
}
複製代碼
佈局文件直接ConstraintLayout
嵌套這個自定義View便可:
<android.support.constraint.ConstraintLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.knight.qq_redpoint.MainActivity">
<com.knight.qq_redpoint.RedPointView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
複製代碼
效果圖以下:
靜態效果繪製出來了,那麼繼續往下走,實現動態效果,實現動態無非是拖拽圓的切點和貝塞爾曲線的控制點在變化,而拖拽圓的圓心實際上是觸摸屏幕的座標,那麼其切點和控制點根據上一個步驟的公式來求出,下面直接在觸摸方法onTouchEvent
來處理:
public boolean onTouchEvent(MotionEvent event){
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//event.getRawX:表示的是觸摸點距離屏幕左邊界的距離
//event.getRawY:表示的是觸摸點距離屏幕上邊界的距離
//event.getX()取相對於你觸摸的view的左邊的偏移(X座標)
//event.getY()取相對於你觸摸的view的頂邊的偏移(Y座標)
float originalDragX = event.getX();
float originalDragy = event.getY();
updateDragPoint(originalDragX,originalDragy);
break;
case MotionEvent.ACTION_MOVE:
float overDragX = event.getX();
float overDragy = event.getY();
//移動的時候不斷更新拖拽圓的位置
updateDragPoint(overDragX,overDragy);
break;
}
return true;
}
//更新拖拽圓的圓心座標
private void updateDragPoint(float x,float y){
tDragPointF.set(x,y);
postInvalidate();
}
複製代碼
效果圖以下:
仔細觀察效果,發現隨着拖拽距離的增長,中心圓的半徑是愈來愈小的 好像有那麼一點點感受了,可是遠遠還不夠。那麼咱們能夠定一個規則,拖拽距離和中心圓之間的關係,而且設置拖拽最大距離:
//中心的最小半徑
private float minRadius = 8;
//默認拖拽最大距離
private float maxDistance = 160;
//計算拖動過程當中中心圓的半徑
private float changeCenterRadius() {
float mDistance_x = tDragPointF.x - tCenterPointF.x;
float mDistance_y = tDragPointF.y - tCenterPointF.y;
//兩個圓之間的距離
float mDistance = (float) Math.sqrt(Math.pow(mDistance_x, 2) + Math.pow(mDistance_y, 2));
//計算中心圓的半徑 這裏用拖拽圓默認的半徑去減距離變化的長度(這裏能夠本身定義變化的半徑)
float r = tDragRadius - minRadius * (mDistance / maxDistance);
//計算出半徑若是小於最小的半徑 就賦值最小半徑
if (r < minRadius) {
r = minRadius;
}
return r;
}
複製代碼
最後在onDraw
方法裏,添加計算變化中心圓的半徑便可:
//繪製方法
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
//繪製固定中心圓
tCenterRadius = changeCenterRadius();
canvas.drawCircle(tCenterPointF.x, tCenterPointF.y, tCenterRadius, rPaint);
....
}
複製代碼
效果圖以下:
下面增長拖拽距離限制,當拖拽距離大於給定的距離時,中心圓就會消失,邏輯很簡單,也就是在onTouchEvent
裏的ACTION_MOVE
,計算兩個圓的拖拽距離,若是超出給定的拖拽距離,就不繪製貝塞爾曲線和中心固定圓:
//標識 拖拽距離是否大於規定的拖拽範圍
private boolean isOut;
//標識 若是超出拖拽範圍
private boolean isOverStep;
//繪製方法
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
if(!isOut){
//繪製固定中心圓
tCenterRadius = changeCenterRadius();
canvas.drawCircle(tCenterPointF.x, tCenterPointF.y, tCenterRadius, rPaint);
.....
}
//一旦超出給定的拖拽距離 就繪製拖拽圓
if(!isOverStep){
canvas.drawCircle(tDragPointF.x,tDragPointF.y,tDragRadius,rPaint);
}
}
//重寫onTouchEvent方法
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
........
case MotionEvent.ACTION_MOVE:
float overDragX = event.getX();
float overDragy = event.getY();
//移動的時候不斷更新拖拽圓的位置
updateDragPoint(overDragX, overDragy);
float tDragDistance = getDistanceTwo(tCenterPointF,tDragPointF);
//判斷若是拖拽距離大於給定距離時
if(tDragDistance > maxDistance){
isOut = true;
}else{
//這裏要注意 不能賦值isOut爲false 由於一旦超出給定的拖拽距離就沒辦法恢復了
isOverStep = false;
}
break;
}
return true;
}
//計算兩個圓之間的距離
private float getDistanceTwo(PointF tCenterPointF,PointF tDragPointF){
return (float) Math.sqrt(Math.pow(tCenterPointF.x - tDragPointF.x,2) + Math.pow(tCenterPointF.y - tDragPointF.y,2));
}
複製代碼
效果圖以下:
上面只作了超出拖拽範圍的效果,下面添加沒有超出拖拽範圍效果,鬆開手後拖拽圓會回彈原來的位置,那就要在MotionEvent.ACTION_UP
作處理:
//重寫onTouchEvent方法
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
....
case MotionEvent.ACTION_UP:
getDistanceTwo(tCenterPointF,tDragPointF);
//這裏要判斷
if(!isOut){
//沒有超出
kickBack();
}
postInvalidate();
break;
}
return true;
}
/** * 拖拽圓回彈動畫 * */
private void kickBack() {
final PointF initPoint = new PointF(tDragPointF.x,
tDragPointF.y);
final PointF finishPoint = new PointF(tCenterPointF.x,
tCenterPointF.y);
//值從0平滑過渡1
ValueAnimator animator = ValueAnimator.ofFloat(0.0f,1.0f);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//獲取動畫執行進度
float rFraction = animation.getAnimatedFraction();
//更新拖拽圓的圓心
PointF updateDragPoint = getPoint(
initPoint, finishPoint, rFraction);
updateDragPoint(updateDragPoint.x, updateDragPoint.y);
}
});
//設置動畫插值器
animator.setInterpolator(new OvershootInterpolator(3.0f));
//動畫時間
animator.setDuration(500);
animator.start();
}
/** * * 根據百分比獲取兩點之間的某個點座標 * @param initPoint 初識圓 * @param finishPoint 最終圓 * @param percent 百分比 * @return * */
public PointF getPoint(PointF initPoint, PointF finishPoint, float percent) {
return new PointF(getValue(initPoint.x , finishPoint.x,percent), getValue(initPoint.y , finishPoint.y,percent));
}
/** * 獲取分度值 * @param start * @param finish * @param fraction * @return */
public float getValue(Number start, Number finish,float fraction){
return start.floatValue() + (finish.floatValue() - start.floatValue()) * fraction;
}
複製代碼
效果圖:
當拖拽圓超出拖拽範圍後,會有一個爆炸效果後並消失,下面添加爆炸效果:
//初始化爆炸圖片
private int[] explodeImgae = new int[]{
R.mipmap.explode_1,
R.mipmap.explode_2,
R.mipmap.explode_3,
R.mipmap.explode_4,
R.mipmap.explode_5
};
//爆炸ImageView
private ImageView explodeImage;
複製代碼
並在init
初始化方法裏添加對這爆炸圖像:
//添加爆炸圖像
explodeImage = new ImageView(getContext());
//設置佈局參數
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
explodeImage.setLayoutParams(lp);
explodeImage.setImageResource(R.mipmap.explode_1);
//一開始不顯示
explodeImage.setVisibility(View.INVISIBLE);
//增長到viewGroup中
addView(explodeImage);
複製代碼
並實現播放動畫方法:
/** * * 超過拖拽範圍外顯示爆炸效果 * */
private void showExplodeImage(){
//屬性動畫
ValueAnimator animator = ValueAnimator.ofInt(0,explodeImgaes.length - 1);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//不斷更新圖像變化
explodeImage.setBackgroundResource(explodeImgaes[(int) animation.getAnimatedValue()]);
}
});
//爲動畫添加監聽
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
super.onAnimationCancel(animation);
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//結束了 把圖像設置不可見狀態
explodeImage.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(Animator animation) {
super.onAnimationRepeat(animation);
}
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
//開始時 設置爲可見
explodeImage.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationPause(Animator animation) {
super.onAnimationPause(animation);
}
@Override
public void onAnimationResume(Animator animation) {
super.onAnimationResume(animation);
}
});
//時間
animator.setDuration(600);
//播放一次
animator.setRepeatMode(ValueAnimator.RESTART);
//差值器
animator.setInterpolator(new OvershootInterpolator());
animator.start();
}
複製代碼
在MotionEvent.ACTION_UP
裏:
case MotionEvent.ACTION_UP:
getDistanceTwo(tCenterPointF,tDragPointF);
//這裏要判斷
if(!isOut){
//沒有超出
kickBack();
}
if(isOut){
//擡起標識
isOverandUp = true;
//讓爆炸圖片在原點中央
explodeImage.setX(event.getX() - tDragRadius);
explodeImage.setY(event.getY() - tDragRadius);
//若是中心圓和拖拽圓大於拖拽距離 就播放爆炸
if(getDistanceTwo(tCenterPointF,tDragPointF) > maxDistance){
showExplodeImage();
}
//這裏是若是拖拽圓和中心圓距離已經超出拖拽距離 而後又把拖拽圓移動與中心圓大於30 仍是會爆炸
if(getDistanceTwo(tCenterPointF,tDragPointF) >=30){
showExplodeImage();
}
}
postInvalidate();
break;
複製代碼
在dispatchView
超出拖拽距離到小於恢復中心圓的距離邏輯:
if(isOut){
//若是一開始超出拖拽範圍 後面又移動拖拽圓與中心圓的距離少於30,就恢復中心圓位置
if(getDistanceTwo(tCenterPointF,tDragPointF) < 30 && isOverandUp){
canvas.drawCircle(tCenterPointF.x, tCenterPointF.y, tCenterRadius, rPaint);
isOut = false;
isOverandUp = false;
}
}
//一旦超出給定的拖拽距離 就繪製拖拽圓
if(!isOverStep){
//若是超出而且擡起
if(!isOverandUp && isOut){
canvas.drawCircle(tDragPointF.x,tDragPointF.y,tDragRadius,rPaint);
}
}
複製代碼
效果圖以下:
上面所實現的效果還遠遠不夠,怎麼像QQ那樣,在ListView或者Recycleview裏小圓點能自由在屏幕內拖拽呢?由於view只能在它的父控件內繪製,因此也只能在本身的列表內移動,那怎麼能在全屏拖拽呢?只能藉助WindowManager,也就是當將要拖拽的圓點添加到windowManager,而且設置觸摸監聽,自定義拖拽view從繼承ViewGroup
變爲繼承View
:
public class BetterRedPointView extends View{
//WindowManager 對象
private WindowManager windowManager;
//拖拽view的寬
private int dragViewWidth;
//拖拽view的高
private int dragViewHeight;
//WindowManager 佈局參數
private WindowManager.LayoutParams params;
//狀態監聽
private DragViewStatusListener dragViewStatusListener;
//佈局參數
params = new WindowManager.LayoutParams();
//背景透明
params.format = PixelFormat.TRANSLUCENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
//以左上角爲基準
params.gravity = Gravity.TOP | Gravity.LEFT;
}
複製代碼
構造函數將拖拽的view
和WindowManager
對象傳進來,並初始化一些參數:
//構造函數
public BetterRedPointView(Context context, View dragView, WindowManager windowManager){
super(context);
this.context = context;
this.dragView = dragView;
this.windowManager = windowManager;
init();
}
//初始化小圓
private void init() {
//手動測量
dragView.measure(1,1);
dragViewWidth = dragView.getMeasuredWidth() / 2;
dragViewHeight = dragView.getMeasuredHeight() / 2;
tDragRadius = dragViewHeight;
//中心圓的半徑
tCenterRadius = SystemUtil.dp2px(context,8);
//最大拖拽距離
maxDistance = SystemUtil.dp2px(context,80);
//最小半徑
minRadius = SystemUtil.dp2px(context,3);
//佈局參數
params = new WindowManager.LayoutParams();
//背景透明
params.format = PixelFormat.TRANSLUCENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
//以左上角爲基準
params.gravity = Gravity.TOP | Gravity.LEFT;
}
複製代碼
在上面例子中更新拖拽圓updateDragPoint
的方法,也一樣經過WindowManager.updateViewLayout
來更新拖拽view
的的位置:
/** * 更新拖拽圓心座標 * @param x * @param y */
private void updateDragPoint(float x, float y) {
tDragPointF.set(x, y);
changeManagerView(x,y);
postInvalidate();
}
/** * 從新繪製拖拽圓的佈局 * @param x x座標 * @param y y座標 */
private void changeManagerView(float x,float y){
params.x = (int)(x - dragViewWidth);
params.y = (int)(y - dragViewHeight - statusBarHeight);
windowManager.updateViewLayout(dragView,params);
}
複製代碼
增長拖拽圓和中心圓的拖拽狀況監聽:
public interface DragViewStatusListener {
/** * 在拖拽範圍外移動 * * @param dragPoint */
void outDragMove(PointF dragPoint);
/** * 在拖拽範圍外移動 * 產生爆炸效果 * */
void outDragMoveUp(PointF dragPoint);
/** * 在拖拽範圍內移動 * * @param dragPoint */
void inDragUp(PointF dragPoint);
/** * 當移出拖拽範圍 後拖拽到範圍內 恢復中心圓 * */
void recoverCenterPoint(PointF centerPoint);
}
複製代碼
在對應觸發的狀況下實現監聽回調,如爆炸的動畫:
case MotionEvent.ACTION_UP:
getDistanceTwo(tCenterPointF,tDragPointF);
//這裏要判斷
if(!isOut){
//沒有超出
kickBack();
}
if(isOut){
//擡起標識
isOverandUp = true;
//讓爆炸圖片在原點中央
//explodeImage.setX(event.getX() - tDragRadius);
//explodeImage.setY(event.getY() - tDragRadius);
//若是中心圓和拖拽圓大於拖拽距離 就播放爆炸
if(getDistanceTwo(tCenterPointF,tDragPointF) > maxDistance){
//這裏監聽作爆炸效果
if(dragViewStatusListener != null){
dragViewStatusListener.outDragMoveUp(tDragPointF);
}
}
//這裏是若是拖拽圓和中心圓距離已經超出拖拽距離 而後又把拖拽圓移動與中心圓大於30 仍是會爆炸
if(getDistanceTwo(tCenterPointF,tDragPointF) >=30){
if(dragViewStatusListener != null){
dragViewStatusListener.outDragMoveUp(tDragPointF);
}
}
}
複製代碼
新建一個類,主要用來輔助,主要用來建立拖拽自定義view
和建立WindowManager
對象初始化數據,而且做出各類狀況下(在範圍內拖拽,範圍外拖拽)的邏輯和爆炸邏輯,主要代碼以下:
public class BetterRedPointViewControl implements View.OnTouchListener,DragViewStatusListener{
//上下文
private Context context;
//拖拽佈局的id
private int mDragViewId;
//WindowManager 對象
private WindowManager windowManager;
//佈局參數
private WindowManager.LayoutParams params;
private BetterRedPointView betterRedPointView;
//被拖拽的View
private View dragView;
//要顯示的View
private View showView;
//狀態欄高度
private int statusHeight;
//最大拖拽距離
private float maxDistance = 560;
//中心圓的半徑
private float tCenterRadius = 30;
//小圓最小半徑
private float minRadius = 8;
//構造函數
public BetterRedPointViewControl(Context context,View showView,int mDragViewId,DragStatusListener dragStatusListener){
this.context = context;
this.showView = showView;
this.mDragViewId = mDragViewId;
this.dragStatusListener = dragStatusListener;
//設置監聽 執行本身的觸摸事件
showView.setOnTouchListener(this);
params = new WindowManager.LayoutParams();
params.format = PixelFormat.TRANSLUCENT;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
if(action == MotionEvent.ACTION_DOWN){
ViewParent parent = v.getParent();
if(parent == null){
return false;
}
parent.requestDisallowInterceptTouchEvent(true);
statusHeight = SystemUtil.getStatusBarHeight(showView);
showView.setVisibility(View.INVISIBLE);
dragView = LayoutInflater.from(context).inflate(mDragViewId,null,false);
//獲取文本內容
getText();
windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
//每當觸摸的時候就建立拖拽的小圓
betterRedPointView = new BetterRedPointView(context,dragView,windowManager);
//初始化數據
init();
//設置監聽回調
betterRedPointView.setDragViewStatusListener(this);
//添加到窗體進行顯示
windowManager.addView(betterRedPointView,params);
windowManager.addView(dragView,params);
}
betterRedPointView.onTouchEvent(event);
return true;
}
@Override
public void outDragMove(PointF dragPoint) {
}
@Override
public void outDragMoveUp(PointF dragPoint) {
removeView();
showExplodeImage(dragPoint);
dragStatusListener.outScope();
}
@Override
public void inDragUp(PointF dragPoint) {
removeView();
dragStatusListener.inScope();
}
@Override
public void recoverCenterPoint(PointF centerPoint) {
removeView();
dragStatusListener.inScope();
}
/** * 初始化數據 * */
private void init(){
//計算小圓在屏幕中的座標
int[] points = new int[2];
showView.getLocationInWindow(points);
int x = points[0] + showView.getWidth() / 2;
int y = points[1] + showView.getHeight() / 2;
betterRedPointView.setStatusBarHeight(statusHeight);
// betterRedPointView.setMaxDistance(maxDistance);
// betterRedPointView.setCenterRadius(tCenterRadius);
// betterRedPointView.setMinRadius(minRadius);
betterRedPointView.setCenterDragPoint(x,y);
}
/** * 獲取文本內容 * */
private void getText(){
if(showView instanceof TextView && dragView instanceof TextView){
((TextView)dragView).setText((((TextView) showView).getText().toString()));
}
}
/** * 移出view對象 * */
private void removeView(){
if (windowManager != null && betterRedPointView.getParent() != null && dragView.getParent() != null) {
windowManager.removeView(betterRedPointView);
windowManager.removeView(dragView);
}
}
}
複製代碼
在Recycleview內執行調用便可:
public class RecycleviewAdapter extends RecyclerView.Adapter<ItemHolder> {
/** * 須要刪除的view的position 用於更新rv操做 */
ArrayList<Integer> needRemoveList =new ArrayList<Integer>();
private Context mContext;
public RecycleviewAdapter(Context mContext){
this.mContext = mContext;
}
@NonNull
@Override
public ItemHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
//加載佈局文件
View itemView = LayoutInflater.from(mContext).inflate(R.layout.item,null);
return new ItemHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull ItemHolder itemHolder, final int i) {
itemHolder.tv_dragView.setText(String.valueOf(i));
Glide.with(mContext).load(R.mipmap.iv_image).apply(RequestOptions.bitmapTransform(new CircleCrop()).override(200,200)).into(itemHolder.iv_head);
//是否隱藏要拖拽的view
if(needRemoveList.contains(i)){
itemHolder.tv_dragView.setVisibility(View.GONE);
}
else {
itemHolder.tv_dragView.setVisibility(View.VISIBLE);
itemHolder.tv_dragView.setText(String.valueOf(i));
}
//一個是拖拽的view 一個是拖拽的view佈局
new BetterRedPointViewControl(mContext, itemHolder.tv_dragView, R.layout.includeview, new BetterRedPointViewControl.DragStatusListener() {
/** * 在範圍內 * */
@Override
public void inScope() {
notifyDataSetChanged();
}
/** * 在範圍外 * */
@Override
public void outScope() {
needRemoveList.add(i);
notifyDataSetChanged();
}
});
}
@Override
public int getItemCount() {
return 100;
}
}
複製代碼
效果圖以下:
github地址:github.com/KnightAndro…