2019新版《黑马javaee基础班+就业班全套教程完整版(第49期)》

private String cacheStr = "";
public class BiuEditText extends EditText {
 
    public BiuEditText(Context context) {
        super(context);
    }
 
    public BiuEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        setlistener();
    }
 
    public BiuEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
 
    /**
     * 输入文字时的监听
     * BiuEditText静态添加进XML布局 所以该监听方法写到第二个构造方法中
     */
    private void setlistener() {
        addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
 
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
 
                if (cacheStr.length() < s.length()) {
                    // 输入文字时
                    char last = s.charAt(s.length() - 1);
                    update(last, false);
                } else if (cacheStr.length() >= 1) {
                    // 删除文字时
                    char last = cacheStr.charAt(cacheStr.length() - 1);
                    update(last, true);
                }
                cacheStr = s.toString();
            }
 
            @Override
            public void afterTextChanged(Editable s) {
 
            }
        });
    }
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="BiuEditStyle">
        <attr name="biu_text_color" format="color" />
        <attr name="biu_text_start_size" format="dimension" />
        <attr name="biu_text_scale" format="float" />
        <attr name="biu_duration" format="integer" />
        <attr name="biu_type" format="enum">
            <enum name="flyup" value="0" />
            <enum name="flydown" value="1" />
        </attr>
 
    </declare-styleable>
</resources>
    private ViewGroup contentContainer;
    private int height;
    private int biuTextColor;
    private float biuTextStartSize;
    private float biuTextScale;
    private int biuDuration;
    private int biuType;
    
    private void init(Context context, AttributeSet attrs) {
        if (isInEditMode())
            return;
 
        if (null == attrs) {
            throw new IllegalArgumentException("Attributes should be provided to this view,");
        }
        final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BiuEditStyle);
        biuTextColor = typedArray.getColor(R.styleable.BiuEditStyle_biu_text_color, getResources().getColor(R.color.white));
        biuTextStartSize = typedArray.getDimension(R.styleable.BiuEditStyle_biu_text_start_size, getResources().getDimension(R.dimen.biu_text_start_size));
        biuTextScale = typedArray.getFloat(R.styleable.BiuEditStyle_biu_text_scale, DEFAULT_SCALE);
        biuDuration = typedArray.getInt(R.styleable.BiuEditStyle_biu_duration, DEFAULT_DURATION);
        biuType = typedArray.getInt(R.styleable.BiuEditStyle_biu_type, 0);
        typedArray.recycle();
 
        /**
         * 关键所在-通过findViewById(android.R.id.content)获取Activity根View布局 跳跃文字都是添加在该容器布局内部
         * 所以点击键盘时,跳跃的TextView是出现在全局中,而不仅仅局限在自定义View所在的位置
         */
        contentContainer = (ViewGroup) ((Activity) getContext()).findViewById(android.R.id.content);
        Log.d("根布局id", "contentContainer: " + contentContainer.getId());
        WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        height = windowManager.getDefaultDisplay().getHeight(); // 获取屏幕的高度 此方法已被废弃 改为 height = getContext().getResource().getDisplayMeytrics().heightPixels;
    }
    /**
     * 动态添加或者动态删除跳跃的TextView
     * @param last
     * @param isOpposite
     */
    private void update(char last, boolean isOpposite) {
        final TextView textView = new TextView(getContext());
        textView.setTextColor(Color.BLUE);
        textView.setTextSize(biuTextStartSize);
        textView.setText(String.valueOf(last));
        textView.setGravity(Gravity.CENTER);
        contentContainer.addView(textView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
 ViewGroup.LayoutParams.WRAP_CONTENT));
        textView.measure(0, 0);
        playAnaimator(textView, isOpposite, new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                contentContainer.removeView(textView);
            }
        });
    }
    private void playAnaimator(TextView textView, boolean isOpposite, AnimatorListenerAdapter listenerAdapter) {
 
        switch (biuType) {
            case ANIMATION_DEFAULT:
                playFlyUp(textView, isOpposite, listenerAdapter);
                break;
            case ANIMATION_DROPOUT:
                playFlyDown(textView, isOpposite, listenerAdapter);
                break;
            default:
                break;
        }
 
    }
 
    /**
     * TextView下落动画
     * @param textView
     * @param isOpposite
     * @param listenerAdapter
     */
    private void playFlyDown(TextView textView, boolean isOpposite, AnimatorListenerAdapter listenerAdapter) {
        int pos = getSelectionStart();
        Layout layout = getLayout();
        float startX = 0;
        float startY = 0;
        float endX = 0;
        float endY = 0;
        if (isOpposite) {
            endX = new Random().nextInt(contentContainer.getWidth());
            endY = 0;
            startX = layout.getPrimaryHorizontal(pos) + 100;
            startY = getY() - 100;
        } else {
            startX = layout.getPrimaryHorizontal(pos) + 100;
            startY = -100;
            endX = startX;
            endY = getY() - 100;
        }
        final AnimatorSet animSet = new AnimatorSet();
        ObjectAnimator animX = ObjectAnimator.ofFloat(textView, "translationX", startX, endX);
        ObjectAnimator alpha = ObjectAnimator.ofFloat(textView, "alpha", 0, 1);
        ObjectAnimator translationY = ObjectAnimator.ofFloat(textView, "translationY", startY, endY);
        // 代码家的28种估值器之一 无比炫酷
        translationY.setEvaluator(new BounceEaseInOut(biuDuration));
        animSet.setDuration(biuDuration);
        animSet.addListener(listenerAdapter);
        animSet.playTogether(alpha, translationY, animX);
        animSet.start();
    }
 
    /**
     * TextView上浮动画
     * @param textView
     * @param isOpposite
     * @param listenerAdapter
     */
    private void playFlyUp(TextView textView, boolean isOpposite, AnimatorListenerAdapter listenerAdapter) {
        // TextView的getSelectionStart()方法用以获取光标的位置
        int pos = getSelectionStart();
        Layout layout = getLayout();
 
        float startX = 0;
        float startY = 0;
        float endX = 0;
        float endY = 0;
        if (isOpposite) {
            endX = new Random().nextInt(contentContainer.getWidth());
            endY = height / 3 * 2;
            startX = layout.getPrimaryHorizontal(pos) + 100;
            startY = getY();
        } else {
            // layout.getPrimaryHorizontal获取光标左边的位置 再加上100px偏移量
            startX = layout.getPrimaryHorizontal(pos) + 100;
            // 屏幕高度的 2/3 这里可以改为用工具类获取键盘的高度
            startY = height / 3 * 2;
            endX = startX;
            endY = getY();
        }
        final AnimatorSet animSet = new AnimatorSet();
        ObjectAnimator animX = ObjectAnimator.ofFloat(textView, "translationX", startX, endX);
        ObjectAnimator animY = ObjectAnimator.ofFloat(textView, "translationY", startY, endY);
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(textView, "scaleX", 1f, biuTextScale);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(textView, "scaleY", 1f, biuTextScale);
        animY.setEvaluator(new ExpoEaseInOut(biuDuration));
        animY.setInterpolator(new DecelerateInterpolator());
        animSet.setDuration(biuDuration);
        animSet.addListener(listenerAdapter);
        animSet.playTogether(animX, animY, scaleX, scaleY);
        animSet.start();
    }
package me.james.biuedittext;
 
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.text.Editable;
import android.text.Layout;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import android.widget.EditText;
import android.widget.TextView;
 
import java.util.Random;
 
import me.james.biuedittext.easing.bounce.BounceEaseInOut;
import me.james.biuedittext.easing.expo.ExpoEaseInOut;
 
/**
 * 作者    james
 * 分析    cpf
 * 文件    BiuEditText
 * 难点    在于如何实现全局添加动态跳跃的TextView
 * 解决    通过findViewById(android.R.id.content)获取Activity根View布局 跳跃文字都是添加在该容器布局内部
 */
public class BiuEditText extends EditText {
    private ViewGroup contentContainer;
    private int height;
    private String cacheStr = "";
    private static final int ANIMATION_DEFAULT = 0;
    private static final int ANIMATION_DROPOUT = 1;
    private static final int DEFAULT_DURATION = 600;
    private static final float DEFAULT_SCALE = 1.2f;
 
    private int biuTextColor;
    private float biuTextStartSize;
    private float biuTextScale;
    private int biuDuration;
    private int biuType;
 
    public BiuEditText(Context context) {
        super(context);
    }
 
    public BiuEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
        setlistener();
    }
 
    public BiuEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }
 
    private void init(Context context, AttributeSet attrs) {
        if (isInEditMode())
            return;
 
        if (null == attrs) {
            throw new IllegalArgumentException("Attributes should be provided to this view,");
        }
        final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BiuEditStyle);
        biuTextColor = typedArray.getColor(R.styleable.BiuEditStyle_biu_text_color, getResources().getColor(R.color.white));
        biuTextStartSize = typedArray.getDimension(R.styleable.BiuEditStyle_biu_text_start_size, getResources().getDimension(R.dimen.biu_text_start_size));
        biuTextScale = typedArray.getFloat(R.styleable.BiuEditStyle_biu_text_scale, DEFAULT_SCALE);
        biuDuration = typedArray.getInt(R.styleable.BiuEditStyle_biu_duration, DEFAULT_DURATION);
        biuType = typedArray.getInt(R.styleable.BiuEditStyle_biu_type, 0);
        typedArray.recycle();
 
        /**
         * 关键所在-通过findViewById(android.R.id.content)获取Activity根View布局 跳跃文字都是添加在该容器布局内部
         * 所以点击键盘时,跳跃的TextView是出现在全局中,而不仅仅局限在自定义View所在的位置
         */
        contentContainer = (ViewGroup) ((Activity) getContext()).findViewById(android.R.id.content);
        Log.d("根布局id", "contentContainer: " + contentContainer.getId());
        WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        height = windowManager.getDefaultDisplay().getHeight(); // 获取屏幕的高度 此方法已被废弃 改为 height = getContext().getResource().getDisplayMeytrics().heightPixels;
    }
 
    /**
     * 输入文字时的监听
     * BiuEditText静态添加进XML布局 所以该监听方法写到第二个构造方法中
     */
    private void setlistener() {
        addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
 
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
 
                if (cacheStr.length() < s.length()) {
                    // 输入文字时
                    char last = s.charAt(s.length() - 1);
                    update(last, false);
                } else if (cacheStr.length() >= 1) {
                    // 删除文字时
                    char last = cacheStr.charAt(cacheStr.length() - 1);
                    update(last, true);
                }
                cacheStr = s.toString();
            }
 
            @Override
            public void afterTextChanged(Editable s) {
 
            }
        });
    }
 
    /**
     * 动态添加或者动态删除跳跃的TextView
     * @param last
     * @param isOpposite
     */
    private void update(char last, boolean isOpposite) {
        final TextView textView = new TextView(getContext());
        textView.setTextColor(Color.BLUE);
        textView.setTextSize(biuTextStartSize);
        textView.setText(String.valueOf(last));
        textView.setGravity(Gravity.CENTER);
        contentContainer.addView(textView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        textView.measure(0, 0);
        playAnaimator(textView, isOpposite, new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                contentContainer.removeView(textView);
            }
        });
    }
 
    private void playAnaimator(TextView textView, boolean isOpposite, AnimatorListenerAdapter listenerAdapter) {
 
        switch (biuType) {
            case ANIMATION_DEFAULT:
                playFlyUp(textView, isOpposite, listenerAdapter);
                break;
            case ANIMATION_DROPOUT:
                playFlyDown(textView, isOpposite, listenerAdapter);
                break;
            default:
                break;
        }
 
    }
 
    /**
     * TextView下落动画
     * @param textView
     * @param isOpposite
     * @param listenerAdapter
     */
    private void playFlyDown(TextView textView, boolean isOpposite, AnimatorListenerAdapter listenerAdapter) {
        int pos = getSelectionStart();
        Layout layout = getLayout();
        float startX = 0;
        float startY = 0;
        float endX = 0;
        float endY = 0;
        if (isOpposite) {
            endX = new Random().nextInt(contentContainer.getWidth());
            endY = 0;
            startX = layout.getPrimaryHorizontal(pos) + 100;
            startY = getY() - 100;
        } else {
            startX = layout.getPrimaryHorizontal(pos) + 100;
            startY = -100;
            endX = startX;
            endY = getY() - 100;
        }
        final AnimatorSet animSet = new AnimatorSet();
        ObjectAnimator animX = ObjectAnimator.ofFloat(textView, "translationX", startX, endX);
        ObjectAnimator alpha = ObjectAnimator.ofFloat(textView, "alpha", 0, 1);
        ObjectAnimator translationY = ObjectAnimator.ofFloat(textView, "translationY", startY, endY);
        // 代码家的28种估值器之一 无比炫酷
        translationY.setEvaluator(new BounceEaseInOut(biuDuration));
        animSet.setDuration(biuDuration);
        animSet.addListener(listenerAdapter);
        animSet.playTogether(alpha, translationY, animX);
        animSet.start();
    }
 
    /**
     * TextView上浮动画
     * @param textView
     * @param isOpposite
     * @param listenerAdapter
     */
    private void playFlyUp(TextView textView, boolean isOpposite, AnimatorListenerAdapter listenerAdapter) {
        // TextView的getSelectionStart()方法用以获取光标的位置
        int pos = getSelectionStart();
        Layout layout = getLayout();
 
        float startX = 0;
        float startY = 0;
        float endX = 0;
        float endY = 0;
        if (isOpposite) {
            endX = new Random().nextInt(contentContainer.getWidth());
            endY = height / 3 * 2;
            startX = layout.getPrimaryHorizontal(pos) + 100;
            startY = getY();
        } else {
            // layout.getPrimaryHorizontal获取光标左边的位置 再加上100px偏移量
            startX = layout.getPrimaryHorizontal(pos) + 100;
            // 屏幕高度的 2/3 这里可以改为用工具类获取键盘的高度
            startY = height / 3 * 2;
            endX = startX;
            endY = getY();
        }
        final AnimatorSet animSet = new AnimatorSet();
        ObjectAnimator animX = ObjectAnimator.ofFloat(textView, "translationX", startX, endX);
        ObjectAnimator animY = ObjectAnimator.ofFloat(textView, "translationY", startY, endY);
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(textView, "scaleX", 1f, biuTextScale);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(textView, "scaleY", 1f, biuTextScale);
        animY.setEvaluator(new ExpoEaseInOut(biuDuration));
        animY.setInterpolator(new DecelerateInterpolator());
        animSet.setDuration(biuDuration);
        animSet.addListener(listenerAdapter);
        animSet.playTogether(animX, animY, scaleX, scaleY);
        animSet.start();
    }
 
}
 

上一篇:Rust 编程视频教程(进阶)——013 使用 Rc 引用计数智能指针


下一篇:PHP常量的定义和用法