Android 书写拍照与录制小视频按钮的Fragment

2018-09-23  本文已影响0人  LazyCoder_MK

        单位要做个录制视频哈拍照的效果,无奈,没有Android 开发经验,不知道去哪里找合适工控件,最主要是不知道这个控件应该叫什么名字

在个人无奈的情况下 写个个动系,希望对要写控件 或者说是要写 动画的 朋友有所帮助把


        在开始前说点没用的:

1 这个控件设计了 Android 动画:帧动画,和属性动画 两种 和和动画插值器【AnimationDrawable ,ObjectAnimator, Interpolator,】附加的其他【PropertyValuesHolder】

2 涉及 android 的 多进程的编程 【Handler,Runnable】

3 涉及 Android 绘画对象  【Drawable】

4 Canvers 的简单用法 

你看看你上面的说明在代码中都有体现 这里简单给大家介绍一下  可跳过

            1 AnimationDrawable  为Android的帧动画的主要对象与渐变动画都  属于传动动画, 但是 Interpolator 插值器,有六种  加速,减速,加速减速,动画回弹,正弦变速,匀速   AccelerateDecelerateInterpolator,AccelerateInterpolator,DecelerateInterpolator,BounceInterpolator,CycleInterpolator,LinearInterpolator  以上插值器 都可以用作属性动画 一定要记得

            2 还有一个是就 窜通动画 TranslateAnimation ,Scale..., Rotate .....,Alpha.... 理解了就理解他们之间的关系就简单了

            3 帮大家理解一下,2 中的渐变豆花为传统动画 他只改变其形 但是不改变其实质 ,TranslateAnimation 初始化后 设置其插值器,完后start 就OK了

 属相动画 改变其形同时也改变其质。

开始吧 打字真的手指头通呀:

一:

创建一个Fragment 

        ButtonFragment.xml

             代码如下:

<?xml version="1.0" encoding="utf-8"?>

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    tools:context=".ButtonFragment">

        android:id="@+id/frame_loyout_container"

        android:layout_width="90dp"

        android:layout_height="90dp">

            android:id="@+id/btn_fragment_bgImg"

            android:layout_width="40dp"

            android:layout_height="40dp"

            android:layout_gravity="center"

            android:background="#cccccc" />

            android:id="@+id/btn_fragment_forImg"

            android:layout_width="30dp"

            android:layout_height="30dp"

            android:layout_gravity="center"

            android:background="#102323" />    

说明一下,这里的两层布局 因为我尝试了一层 他会出现无法改变布局大小的现象,感兴趣的可以试一下

    

后台代码开始处理计划目标, 这里我将注释全部添加到代码上方便 理解

package com.app.yispace.app.anmationdemo;

import android.animation.ObjectAnimator;

import android.animation.PropertyValuesHolder;

import android.annotation.SuppressLint;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.ColorFilter;

import android.graphics.Paint;

import android.graphics.PixelFormat;

import android.graphics.RectF;

import android.graphics.drawable.AnimationDrawable;

import android.graphics.drawable.Drawable;

import android.net.Uri;

import android.os.Build;

import android.os.Bundle;

import android.os.Handler;

import android.support.annotation.NonNull;

import android.support.annotation.Nullable;

import android.support.annotation.RequiresApi;

import android.support.v4.app.Fragment;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.view.animation.AccelerateInterpolator;

import android.widget.FrameLayout;

import android.widget.ImageView;

import android.widget.RelativeLayout;

import java.lang.reflect.Type;

/**

* A simple {@link Fragment} subclass.

* Activities that contain this fragment must implement the

* {@link ButtonFragment.OnFragmentInteractionListener} interface

* to handle interaction events.

* Use the {@link ButtonFragment#newInstance} factory method to

* create an instance of this fragment.

*/

public class ButtonFragment extends Fragment {

    private OnFragmentInteractionListener mListener;

    // 这是背景图片 要绘制圆形的imageView

    ImageView bgimg;

    //这是大家可以见见的中间的ImageView

    ImageView forimg;

    /// 这里是容器空间包含了俩个ImageView

    FrameLayout containerframe;

    /// 我们自己定义的动画对象

    YSAnimationDrawable myAnimationDrawable;

    String TAG = "LazyCoder";

    /// 这是我们处理事件的外界接口状态所

    TONCHSTATE tonchstate = TONCHSTATE.TONCH;

    //这是动画 结束但手为松开的 定时器

    Handler handler = new Handler();

    // 则是处理执行动画的时间

    int timeLenght = 10;

    public ButtonFragment() {

        // Required empty public constructor

    }

    public static ButtonFragment newInstance() {

        ButtonFragment fragment = new ButtonFragment();

        Bundle args = new Bundle();

        fragment.setArguments(args);

        return fragment;

    }

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        if (getArguments() != null) {

        }

    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)

    @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container,

                            Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_button, container, false);

        ;

        bgimg = view.findViewById(R.id.btn_fragment_bgImg);

        forimg = view.findViewById(R.id.btn_fragment_forImg);

        containerframe = view.findViewById(R.id.frame_loyout_container);

        // 上面的就不会了

        //这个方法是舒适化 动画的

        initanimationDrawable();

        // 设置点击事件 的两个监听

        containerframe.setOnTouchListener(new View.OnTouchListener() {

            @Override

            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {

                    case MotionEvent.ACTION_DOWN://0

                        tonchstate = TONCHSTATE.TONCH;//改变状态信息

                        StartAnimation();  // 设置空间的属相动画,大小

                        break;

                    case MotionEvent.ACTION_UP://1

                        if (tonchstate != TONCHSTATE.NULL) { // 这里要 因为有一个定时器,在处理我们的这个状态所以要判断一下

                            myAnimationDrawable.stop(); // 停止背景动画。也就是帧动画 因为,帧动画的开始是长按

                            EndAnimation();// 设置空间的属相动画,大小

                            if (mListener != null) {

                                mListener.StopAtion(tonchstate);

                            }

                            tonchstate = TONCHSTATE.NULL;

                        }

                        break;

                    case MotionEvent.ACTION_MOVE://2

                        break;

                }

                return false;

            }

        });

        // 这是长按

        containerframe.setOnLongClickListener(new View.OnLongClickListener() {

            @Override

            public boolean onLongClick(View v) {

                myAnimationDrawable.start();//开始帧动画

                tonchstate = TONCHSTATE.LONGTONCH;// 改变状态

                if (mListener != null)

                    mListener.StartLongTonch(); //这里就是给外界提供的接口 用于处理

                handler.postDelayed(new Runnable() {// 这里就是处理 长时间按住后不放开的处理

                    @Override

                    public void run() {

                        if (tonchstate != TONCHSTATE.NULL) { // 这里和上面说的那个一样 因为有时间为结束就只想了这个事件状态

                            myAnimationDrawable.stop();

                            EndAnimation();

                            tonchstate = TONCHSTATE.NULL;

                            if (mListener != null) {

                                mListener.StopAtion(tonchstate);

                            }

                        }

                    }

                }, timeLenght * 1000);

                return false;

            }

        });

        return view;

    }

    private void EndAnimation() {

        // s属相动画 修改 放缩 X轴

        ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(forimg,

                "scaleX", 0.5f, 1f).setDuration(500);

        objectAnimatorX.setInterpolator(new AccelerateInterpolator());

        objectAnimatorX.start();

        // s属相动画 修改 放缩 Y轴

        ObjectAnimator ojectAnimatorY = ObjectAnimator.ofFloat(forimg, "scaleY",

                0.5f, 1f).setDuration(500);

        ojectAnimatorY.setInterpolator(new AccelerateInterpolator());

        ojectAnimatorY.start();

        /// 这个是 另一种写法 哈哈哈

        PropertyValuesHolder propertyValuesHolderscaleP_X = PropertyValuesHolder

                .ofFloat

                        ("scaleX", 1.3f, 1f);

        PropertyValuesHolder propertyValuesHolderscaleP_Y = PropertyValuesHolder

                .ofFloat

                        ("scaleY", 1.3f, 1f);

        ObjectAnimator.ofPropertyValuesHolder

                (bgimg, propertyValuesHolderscaleP_X, propertyValuesHolderscaleP_Y)

                .setDuration(500).start();

    }

    private void StartAnimation() {

        PropertyValuesHolder propertyValuesHolderscaleX = PropertyValuesHolder.ofFloat

                ("scaleX", 1f, 0.5f);

        PropertyValuesHolder propertyValuesHolderscale = PropertyValuesHolder.ofFloat

                ("scaleY", 1f, 0.5f);

        ObjectAnimator.ofPropertyValuesHolder

                (forimg, propertyValuesHolderscaleX, propertyValuesHolderscale)

                .setDuration(500).start();

        PropertyValuesHolder propertyValuesHolderscalePX = PropertyValuesHolder

                .ofFloat

                        ("scaleX", 1f, 1.3f);

        PropertyValuesHolder propertyValuesHolderscalePY = PropertyValuesHolder

                .ofFloat

                        ("scaleY", 1f, 1.3f);

        ObjectAnimator.ofPropertyValuesHolder

                (bgimg, propertyValuesHolderscalePX, propertyValuesHolderscalePY)

                .setDuration(500).start();

    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)

    private void initanimationDrawable() {

        myAnimationDrawable = new YSAnimationDrawable(timeLenght, Paint.Style.STROKE);

        bgimg.setBackground(myAnimationDrawable.build().getAnimationDrawable());

        forimg.setBackground(new ForDrawable("#ffffff"));

    }

    @Override

    public void onAttach(Context context) {

        super.onAttach(context);

        if (context instanceof OnFragmentInteractionListener) {

            mListener = (OnFragmentInteractionListener) context;

        } else {

//            throw new RuntimeException(context.toString()

//                    + " must implement OnFragmentInteractionListener");

        }

    }

    @Override

    public void onDetach() {

        super.onDetach();

        mListener = null;

    }

    public void setmListener(OnFragmentInteractionListener mListener) {

        this.mListener = mListener;

    }

    ///状态属性的 枚举

    public enum TONCHSTATE {

        LONGTONCH,

        TONCH,

        NULL,

    }

    public interface OnFragmentInteractionListener {

        void StopAtion(TONCHSTATE state);

        void StartLongTonch();

    }

    // 自定义的动画容器

    class YSAnimationDrawable {

        // 这个是针动画

        AnimationDrawable animationDrawable = new AnimationDrawable();

        // 检测属性

        boolean isBuild = false;

        Paint.Style style;

        int DEPLEYTIME = 25;

        int TimeLength;

        int angle;

        int strokeWidth = 5;

        String bgRGB = "#6f6f71";

        String corcleLineRGB = "#00ff00";

        public YSAnimationDrawable(int timeLength, Paint.Style style) {

            TimeLength = timeLength;

            this.style = style;

        }

        public YSAnimationDrawable(int timeLength) {

            TimeLength = timeLength;

        }

        public AnimationDrawable getAnimationDrawable() {

            return animationDrawable;

        }

        public YSAnimationDrawable build() {

            setAnimationDrawableCore();

            float angle = 360f / (TimeLength * DEPLEYTIME);

            float cangile = 0;

            int i = 1;

            while (true) {

                cangile = angle * i;

                YsDrawable drawable = new YsDrawable(Math.round

                        (cangile), bgRGB, corcleLineRGB,

                        style, strokeWidth);

                animationDrawable.addFrame(drawable, 40);

                i++;

                if (cangile >= 360)

                    break;

            }

            isBuild = true;

            return this;

        }

        private void setAnimationDrawableCore() {

            animationDrawable.setOneShot(true);

        }

        public void start() {

            if (isBuild == false)

                throw new ExceptionInInitializerError("You not Invoke build Function");

            animationDrawable.setVisible(true, false);

            animationDrawable.start();

        }

        public void stop() {

            animationDrawable.setVisible(true, true);

            animationDrawable.stop();

        }

    }

    class YsDrawable extends Drawable {

        int sweepleAngle;

        Paint paint;

        String bgRGB = "#6f6f71";

        String corcleLineRGB = "#00ff00";

        Paint.Style style;

        int strokeWidth;

        public YsDrawable(int sweepleAngle, String bgRGB, String corcleLineRGB, Paint.Style style, int strokeWidth) {

            this.sweepleAngle = sweepleAngle;

            this.bgRGB = bgRGB;

            this.corcleLineRGB = corcleLineRGB;

            this.style = style;

            this.strokeWidth = strokeWidth;

            InitParam();

        }

        public int getSweepleAngle() {

            return sweepleAngle;

        }

        private void InitParam() {

            paint = new Paint();

            paint.setAntiAlias(true);

            paint.setStrokeWidth(strokeWidth);

            paint.setStyle(style);

            paint.setColor(Color.parseColor(corcleLineRGB));

            paint.setStrokeCap(Paint.Cap.BUTT);

        }

        /**

        * Draw in its bounds (set via setBounds) respecting optional effects such

        * as alpha (set via setAlpha) and color filter (set via setColorFilter).

        *

        * @param canvas The canvas to draw into

        */

        @Override

        public void draw(@NonNull Canvas canvas) {

            int x = canvas.getWidth();

            int y = canvas.getHeight();

            int minOne = x > y ? y / 2 : x / 2;

            Float padding = paint.getStrokeWidth() / 2;

            Paint cpaint = new Paint();

            cpaint.setAntiAlias(true);

            cpaint.setStyle(Paint.Style.FILL);

            cpaint.setColor(Color.parseColor(bgRGB));

            canvas.drawCircle((float) minOne, (float) minOne, (float) minOne, cpaint);

            RectF rectF = new RectF(padding, padding, canvas.getHeight() - paint.getStrokeWidth()

                    , canvas.getWidth() - paint.getStrokeWidth());

            canvas.drawArc(rectF, -90, sweepleAngle, false, paint);

        }

        @Override

        public void setAlpha(int alpha) {

        }

        @Override

        public void setColorFilter(@Nullable ColorFilter colorFilter) {

        }

        @SuppressLint("WrongConstant")

        @Override

        public int getOpacity() {

            return 0;

        }

    }

    class ForDrawable extends Drawable {

        public ForDrawable(String forRGB) {

            this.forRGB = forRGB;

        }

        public void setForRGB(String forRGB) {

            this.forRGB = forRGB;

        }

        String forRGB = null;

        @Override

        public void draw(@NonNull Canvas canvas) {

            int x = canvas.getWidth() / 2;

            Paint paint = new Paint();

            paint.setStyle(Paint.Style.FILL);

            paint.setColor(Color.parseColor(forRGB));

            canvas.drawCircle(x, x, x, paint);

        }

        @Override

        public void setAlpha(int alpha) {

        }

        @Override

        public void setColorFilter(@Nullable ColorFilter colorFilter) {

        }

        @SuppressLint("WrongConstant")

        @Override

        public int getOpacity() {

            return 0;

        }

    }

}

    以上我感觉需要注释的都给了 有不明白的我可以在给你添加说明

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:id="@+id/frame_loyout_name"

  android:name="com.app.yispace.app.anmationdemo.ButtonFragment"

  >

四 效果:

默认效果 按下的效果
上一篇下一篇

猜你喜欢

热点阅读