美文网首页
Android 书写拍照与录制小视频按钮的Fragment

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

作者: LazyCoder_MK | 来源:发表于2018-09-23 15:34 被阅读0次

            单位要做个录制视频哈拍照的效果,无奈,没有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"

      >

    四 效果:

    默认效果 按下的效果

    相关文章

      网友评论

          本文标题:Android 书写拍照与录制小视频按钮的Fragment

          本文链接:https://www.haomeiwen.com/subject/kzafoftx.html