Android之自定义View

本文介绍了一个Android项目的实现,该项目通过监听滑动事件创建了三个可左右滑动的Button,中间Button有突出显示的放大动画效果。项目源码可在GitHub上找到。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要是记录一些零碎的东西

项目地址:https://github.com/CL-window/MyView

1 . 实现三个button ,可以左右滑动(动画效果),中间的一个突出显示(放大)


其实没啥,就是监听了滑动事件,只是动画太丑

/**
 * <p>Description:  中间突出的滑动 button </p>
 * Created by slack on 2016/7/11 11:00 .
 * 动画添加失败,以后再处理
 */
public class showCenter extends LinearLayout implements View.OnClickListener {

    private double downX,upX;
    private double threshold = 30;// 滑动阈值
    private int[] smallIco = {R.drawable.video,R.drawable.camera,R.drawable.gifp};// 小图 录像 拍照 gif
    private int[] bigIco = {R.drawable.video_large,R.drawable.camera_large,R.drawable.gifp_large};// 录像 拍照 gif
    private String[] bigIcoInfo = {"录像", "拍照", "GIF"};
    private int centerSelect = 1;
    private View view;
    private ImageView leftImage,centerImage,rightImage,tempImage;
    private TextView centerInfo;
    private ShowCenterListener mShowCenterListener;


    public showCenter(Context context) {
        super(context);
    }
    public showCenter(Context context, AttributeSet attrs) {
        super(context, attrs);
//        setWillNotDraw(false);// 关于onDraw()方法不被执行的解决方法
        view = LayoutInflater.from(context).inflate(R.layout.bottomview, this);
        initView();
        initListener();

    }

    private void initView() {
        leftImage = (ImageView) view.findViewById(R.id.bottom_view_left);
        centerImage =(ImageView)  view.findViewById(R.id.bottom_view_center_big);
        rightImage = (ImageView)view.findViewById(R.id.bottom_view_right);
        centerInfo = (TextView)view.findViewById(R.id.bottom_view_center_info);

        
    }
    private void initListener() {
        view.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {

                switch (motionEvent.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        downX = motionEvent.getX();
//                        Log.i("slack","ACTION_DOWN..."+downX);
                        break;
                    case MotionEvent.ACTION_MOVE:
//                        Log.i("slack","ACTION_MOVE...");
                        // 滑动中开始动画

                        break;
                    case MotionEvent.ACTION_UP:
                        upX = motionEvent.getX();
//                        Log.i("slack","ACTION_UP..."+upX);
                        if(downX - upX > threshold){
                            Log.i("slack","left...1");
                            leftSelect();
                        }else if(upX - downX > threshold){
                            Log.i("slack","right...1");
                            rightSelect();
                        }



//                        invalidate();//
                        changeView();
                        break;
                    default: break;
                }
                return true;
            }
        });
        leftImage.setOnClickListener(this);
        centerImage.setOnClickListener(this);
        rightImage.setOnClickListener(this);
        centerInfo.setOnClickListener(this);
    }

    private void leftSelect() {
        if(centerSelect > 2 ){
            centerSelect = 0;
        }
        centerSelect = (centerSelect + 1) % 3;
        

        startAnim();

    }

    private void startAnim() {
       
        animCreate(leftImage);
        animCreate(centerImage);
        animCreate(rightImage);
    }

    private void rightSelect() {
        if(centerSelect < 0){
            centerSelect = 2;
        }
        centerSelect = (centerSelect + 2) % 3;
        
        startAnim();
    }

    public AnimatorSet animCreate(ImageView imageView){

        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator oaX = ObjectAnimator.ofFloat(imageView, "scaleX", 0.5f, 1f);
        ObjectAnimator oaY = ObjectAnimator.ofFloat(imageView, "scaleY", 0.5f, 1f);
        ObjectAnimator oaA = ObjectAnimator.ofFloat(imageView, "alpha", 0.0f, 1f);
        animatorSet.play(oaX).with(oaY).with(oaA);
        animatorSet.setDuration(800);
        animatorSet.setInterpolator(new OvershootInterpolator());
//        animatorSet.setStartDelay(300);
        animatorSet.start();
        return animatorSet;
    }

    private void changeView() {
        leftImage.setImageResource(smallIco[(centerSelect + 2) % 3]);
        centerImage.setImageResource(bigIco[centerSelect % 3]);
        centerInfo.setText(bigIcoInfo[centerSelect]);
        rightImage.setImageResource(smallIco[(centerSelect + 1) % 3]);

        if(mShowCenterListener != null) {
            mShowCenterListener.onSliding(centerSelect);
        }

    }


    public showCenter(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        Log.i("slack","onLayout...3");

        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Log.i("slack","onDraw...4");
        super.onDraw(canvas);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.i("slack","onMeasure...2");
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.bottom_view_left:
                rightSelect();
                changeView();
                break;
            case R.id.bottom_view_center_big:
            case R.id.bottom_view_center_info:
                if(mShowCenterListener != null){
                    mShowCenterListener.onCenterClick();
                }
                break;
            case R.id.bottom_view_right:
                leftSelect();
                changeView();
                break;
            default: break;
        }
    }

    // 设置监听
    public void setListener(ShowCenterListener showCenterListener){
        mShowCenterListener = showCenterListener;
    }

    interface ShowCenterListener{
        void onSliding(int mode);// 滑动监听 提供当前中间的按钮模式 ( 0:录像  1:拍照  2:gif)
        void onCenterClick();// 点击中间的按钮(拍照或者gif或者录像) 监听
    }
}


2. progressbar 实现一个计时器,计时完成做相应的动作


代码:
/**
 * <p>Description: 自定义 ProgressBar ,倒计时效果,</p>
 * Created by slack on 2016/7/12 15:16 .
 */
public class MyProgressBar extends LinearLayout {

    private ProgressBar mProgressBar;
    private Handler mHandler;
    private int maxTime = 0;
    private ProgressListener mProgressListener;

    public MyProgressBar(Context context) {
        super(context);
    }

    public MyProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        mProgressBar = (ProgressBar)LayoutInflater.from(context).inflate(R.layout.progressbar, this).findViewById(R.id.progressBar);
        mHandler = new Handler();
    }

    public MyProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     *
     * @param maxTime 时间(秒)
     */
    public void setMax(int maxTime) {
        this.maxTime = maxTime;
        mProgressBar.setProgress(1);
        mProgressBar.setMax(maxTime);
        mHandler.post(timeCount);
    }

    Runnable timeCount = new Runnable() {
        @Override
        public void run() {
//            Log.i("slack","timeCount " + mProgressBar.getProgress() + "," + maxTime);
            if(mProgressBar.getProgress() < maxTime) {
                mProgressBar.incrementProgressBy(1);
                if(mProgressListener != null){
                    mProgressListener.progress(mProgressBar.getProgress());
                }
                mHandler.postDelayed(timeCount, 1000);
            }else{
                if(mProgressListener != null){
                    mProgressListener.finish();
                }
                mHandler.removeCallbacks(timeCount);
//                Log.i("slack","timeCount finish...");
            }

        }
    };

    public interface ProgressListener{
        void progress(int progress);
        void finish();// 计时完成操作,这个控件需要dismiss
    }
}
使用:布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:orientation="vertical"
    tools:context="com.example.bigview.MainActivity">


    <com.example.bigview.MyProgressBar
        android:id="@+id/progress"
        android:layout_width="match_parent"
        android:layout_height="20dp"></com.example.bigview.MyProgressBar>


   <!-- <com.example.bigview.showCenter
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello World!" />-->

</LinearLayout>

activity里  ((MyProgressBar)findViewById(R.id.progress)).setMax(20);


3. seekBar 动画显示当前进度

看看自定义的view
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.support.v7.widget.ActionBarOverlayLayout;
import android.support.v7.widget.AppCompatSeekBar;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.OvershootInterpolator;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;

/**
 * <p>Description:  </p>
 * Created by slack on 2016/7/18 13:14 .
 */
public class MySeekBar extends LinearLayout {

    private View view;
    private SeekBar mSeekBar;
    private SeekBarProgress mSeekBarProgress;
    private TextView proressInfo;
    private float progres = 0;

    public MySeekBar(Context context) {
        super(context);
    }

    public MySeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        view = LayoutInflater.from(context).inflate(R.layout.seekbar, this);

        init();
    }

    public MySeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {
        proressInfo = (TextView)view.findViewById(R.id.progress_info);
        mSeekBar = (SeekBar) view.findViewById(R.id.my_seekbar);
        changeInfoX();
        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
//                Log.i("slack","onProgressChanged:" + progress);
                progres = progress;
                proressInfo.setText( progress + "%");

                animBig(proressInfo);
                if(mSeekBarProgress != null){
                    mSeekBarProgress.onSeekProgress(progress);
                }
                changeInfoX();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
//                Log.i("slack","onStartTrackingTouch...");
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
//                Log.i("slack","onStopTrackingTouch..." +mSeekBar.getX() +","+
//                        (progres / 100) + "," +
//                        mSeekBar.getWidth() + "," +mSeekBar.getMeasuredWidth() + ","+
//                        (proressInfo.getMeasuredWidth() / 2) + "," +
//                        (mSeekBar.getMeasuredWidth() * (progres / 100) + mSeekBar.getX() ));
                // proressInfo 位置:progress点的位置上
                changeInfoX();
                animCreate(proressInfo);
            }
        });
    }

    private void changeInfoX() {
        proressInfo.setX( mSeekBar.getMeasuredWidth() * (progres / 100) + mSeekBar.getX() - (proressInfo.getMeasuredWidth() / 2) );
    }

    public AnimatorSet animCreate(View view){

        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator oaX = ObjectAnimator.ofFloat(view, "scaleX",0.5f, 1.0f, 0.5f);
        ObjectAnimator oaY = ObjectAnimator.ofFloat(view, "scaleY", 0.5f, 1.0f, 0.5f);
        ObjectAnimator oaA = ObjectAnimator.ofFloat(view, "alpha", 0.5f , 1.0f, 0.5f);
        animatorSet.play(oaX).with(oaY).with(oaA);
        animatorSet.setDuration(800);
        animatorSet.setInterpolator(new OvershootInterpolator());
//        animatorSet.setStartDelay(100);
        animatorSet.start();
        return animatorSet;
    }

    public AnimatorSet animBig(View view){

        AnimatorSet animatorSet = new AnimatorSet();
        ObjectAnimator oaX = ObjectAnimator.ofFloat(view, "scaleX",0.5f, 2.0f);
        ObjectAnimator oaY = ObjectAnimator.ofFloat(view, "scaleY", 0.5f, 2.0f);
        ObjectAnimator oaA = ObjectAnimator.ofFloat(view, "alpha", 0.5f , 1f);
        animatorSet.play(oaX).with(oaY).with(oaA);
        animatorSet.setDuration(0);
        animatorSet.setInterpolator(new OvershootInterpolator());
        animatorSet.start();
        return animatorSet;
    }


    public void setmSeekBarProgress(SeekBarProgress mSeekBarProgress) {
        this.mSeekBarProgress = mSeekBarProgress;
    }

    interface SeekBarProgress{
        void onSeekProgress(int progress);
    }

}
布局文件 seekbar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/progress_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="5dp"
        android:background="@drawable/border_progress_info"
        />

    <android.support.v7.widget.AppCompatSeekBar
        android:id="@+id/my_seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:minHeight="2dp"
        android:maxHeight="2dp"
        android:max="100"
        android:progress="20"
        android:progressDrawable="@drawable/bg_seekbar"/>

</LinearLayout>






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值