package com.xunao.effectdemo.activity; import static com.blankj.utilcode.util.ScreenUtils.getScreenHeight; import static com.blankj.utilcode.util.ScreenUtils.getScreenWidth; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.res.ResourcesCompat; import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Activity; import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import android.util.TypedValue; import android.view.DragEvent; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.TranslateAnimation; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.xunao.effectdemo.R; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.Timer; import java.util.TimerTask; public class DragActivity extends Activity{ private static final String RED = "RED"; RelativeLayout select_rl; RelativeLayout rl_bg; TextView tv_content; //进行滑动的TextView private TextView moveTextView; List selectList; private int answerSize = 0; private int halfAnswerSize = 0; private int selectRootWidth = 0; private int selectRootHeight = 0; //选项位置的集合。初始的显示位置。用于后续拖动松手后,选项做回归动画 private List selectInitialLocationList; //分隔符 private String SeparateSymbol = "-"; //认为的最小滑动值。超过这个值,就认为是滑动;如果没有超过,就是认为是点击 private int reputeMixMoveValue = 10; //按下时候的x,y坐标 private float downX = 0; private float downY = 0; //当前点击或者按住了哪个选项 private int currentOptionPosition = -1; //移动、滑动时候,当前位置的x,y坐标 private float moveCurrentX; private float moveCurrentY; private String selectedContent = ""; private final String correctAnswer = "选项2"; private int wrongNum = 0; Timer timer = new Timer(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_drag); tv_content = findViewById(R.id.tv_content); select_rl = findViewById(R.id.select_rl); rl_bg = findViewById(R.id.rl_bg); initData(); } void initData(){ selectInitialLocationList = new ArrayList<>(); // 选项集合 List selectList = new ArrayList<>(); selectList.add("选项1"); selectList.add("选项2"); selectList.add("选项3"); this.selectList = selectList; answerSize = dp2px(50); halfAnswerSize = answerSize / 2; ViewTreeObserver.OnGlobalLayoutListener listener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { View view = new View(DragActivity.this); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.width = getScreenWidth()/2; params.height = getScreenHeight(); view.setLayoutParams(params); view.setBackgroundColor(getResources().getColor(R.color.textGrayColor)); rl_bg.addView(view); select_rl.getViewTreeObserver().removeOnGlobalLayoutListener(this); handleSelect(); } }; select_rl.getViewTreeObserver().addOnGlobalLayoutListener(listener); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: if (moveTextView != null) { break; } currentOptionPosition = -1; downX = event.getX(); downY = event.getY(); //指定当前滑动的TextView for (int i = 0; i < selectInitialLocationList.size(); i++) { float x1 = Float.parseFloat(selectInitialLocationList.get(i).split(SeparateSymbol)[0]); float x2 = x1 + answerSize*4; float y1 = Float.parseFloat(selectInitialLocationList.get(i).split(SeparateSymbol)[1]); float y2 = y1 + answerSize; //x1、y1,是选项左上角的坐标。x2、y2,是选项右下角的坐标 if (downX > x1 && downX < x2 && downY > y1 && downY < y2) { if(select_rl.getChildAt(i).getVisibility() == View.VISIBLE){ //拿到当前选择的这个选项的view moveTextView = (TextView) select_rl.getChildAt(i); //记下现在选的,是第几个选项 currentOptionPosition = i; Log.e("按下", currentOptionPosition + ""); break; } } } break; case MotionEvent.ACTION_MOVE: if (moveTextView == null) { return false; } moveCurrentX = event.getX(); moveCurrentY = event.getY(); if (Math.abs(moveCurrentX - downX) > reputeMixMoveValue && Math.abs(moveCurrentY - downY) > reputeMixMoveValue) { //这里,按下的坐标,要减去选项的一半,让选项的中间,跟着手指动。否则,就是选项的左上角,跟着手指移动,不美观 moveTextView.setX(moveCurrentX - halfAnswerSize); moveTextView.setY(moveCurrentY - halfAnswerSize); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (moveTextView == null) { return false; } // 当移动到答案框内时 if(moveCurrentX > tv_content.getX() && moveCurrentX < tv_content.getX() + tv_content.getWidth() && moveCurrentY >tv_content.getY() && moveCurrentY < tv_content.getY() + tv_content.getHeight()){ // 正确答案 if(selectList.get(currentOptionPosition).equals(correctAnswer)){ tv_content.setText(selectList.get(currentOptionPosition)); tv_content.setBackground(ResourcesCompat.getDrawable(getResources(),R.drawable.drag_success_bg, null)); moveTextView = null; select_rl.getChildAt(currentOptionPosition).setVisibility(View.INVISIBLE); }else{ // 错误答案 // 先抖一抖再回去 wrongAnimator(); } }else { //说明没有放到答案框,就做回归动画 moveAnimator(0, 0, 0, 0, 0, -1); } break; default: break; } return true; } //处理选项。计算选项,摆放选项的位置 private void handleSelect() { selectRootWidth = select_rl.getWidth(); selectRootHeight = select_rl.getHeight(); //移除之前的子控件(避免数据造成冲突) select_rl.removeAllViews(); float x = 0; float y = 0; for (int i = 0; i < selectList.size(); i++) { String option = selectList.get(i); TextView tvAnswer = createSelectTv(option); x = getScreenWidth()*3/5; y = getScreenHeight()/4 + dp2px(80) * i; //这里的setX、setY,是指选项(正方形)左上角的坐标位置 tvAnswer.setX(x); tvAnswer.setY(y); //保存这个选项的坐标位置 selectInitialLocationList.add(x + SeparateSymbol + y); select_rl.addView(tvAnswer); } } /** * 创建选项TextView * * @param str textView上要展示的内容 * @return */ private TextView createSelectTv(String str) { TextView tv = new TextView(this); tv.setBackground(ResourcesCompat.getDrawable(getResources(),R.drawable.drag_default_bg,null)); tv.setText(str); tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.width = answerSize*4; params.height = answerSize; tv.setLayoutParams(params); tv.setGravity(Gravity.CENTER); return tv; } // 抖一抖动画 private void wrongAnimator(){ wrongNum = wrongNum + 1; Animation anim = AnimationUtils.loadAnimation(DragActivity.this, R.anim.myanim); tv_content.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.drag_error_bg, null)); tv_content.setText(selectList.get(currentOptionPosition)); tv_content.startAnimation(anim); moveTextView.setVisibility(View.GONE); //抖完后回去 timer.schedule(new TimerTask() { @Override public void run() { runOnUiThread(() -> { tv_content.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.drag_default_bg, null)); tv_content.setText(""); moveAnimator(0, 0, 0, 0, 0, -1); }); } }, 1200); } /** * 回归动画 * type: * 0、没有拖动到空格处,松开手后控件回到初始位置 * 1、拖动到空格处,松开手后,隐藏控件,静默回归 * 2、点击选项,控件移动到空缺的位置 * 3、点击选项,内容填充到空格处后,控件需要静默回归 */ private void moveAnimator(final int type, float sX, float sY, float eX, float eY, final int position) { Log.e("type is ", type + ""); Log.e("currentOptionPosition ", currentOptionPosition + ""); if (currentOptionPosition == -1 || moveTextView == null) { return; } moveTextView.setVisibility(View.VISIBLE); try { float startX = 0; float startY = 0; float endX = 0; float endY = 0; AnimatorSet animatorSet = new AnimatorSet(); ObjectAnimator translationX; ObjectAnimator translationY; String location = selectInitialLocationList.get(currentOptionPosition); startX = moveTextView.getX(); startY = moveTextView.getY(); endX = Float.parseFloat(location.split(SeparateSymbol)[0]); endY = Float.parseFloat(location.split(SeparateSymbol)[1]); translationX = ObjectAnimator.ofFloat( moveTextView, "translationX", startX, endX ); translationY = ObjectAnimator.ofFloat( moveTextView, "translationY", startY, endY ); animatorSet.playTogether(translationX, translationY); long durationTime = 1000; animatorSet.setDuration(durationTime); animatorSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { } @Override public void onAnimationEnd(Animator animator) { //抬起手后,释放滑动的TextView moveTextView = null; currentOptionPosition = -1; if(wrongNum > 2){ for(int i = 0; i < select_rl.getChildCount(); i ++){ if(((TextView) select_rl.getChildAt(i)).getText().equals(correctAnswer)){ ((TextView) select_rl.getChildAt(i)).setBackground(ResourcesCompat.getDrawable(getResources(),R.drawable.drag_hint_bg,null)); } } } } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); animatorSet.start(); } catch (Exception e) { e.printStackTrace(); } } private int dp2px(float dpValue) { final float scale = getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } }