Android自定义控件使用-仿ios来电接听按钮


  • 开发自定义控件步骤

1.编写继承自View的子类或viewGroup的子类 2.为自定义View类增加属性 3.绘制控件 4.响应用户消息 5.自定义回调函数

  • 自定义控件的一些方法
    onFinishInflate() 回调方法,当应用从XML加载该组件并用它构建界面之后调用的方法
    onMeasure() 检测View组件及其子组件的大小
    onLayout() 当该组件需要分配其子组件的位置、大小时
    onSizeChange() 当该组件的大小被改变时
    onDraw() 当组件将要绘制它的内容时
    onKeyDown 当按下某个键盘时
    onKeyUp 当松开某个键盘时
    onTrackballEvent 当发生轨迹球事件时
    onTouchEvent 当发生触屏事件时
    onWindowFocusChanged(boolean) 当该组件得到、失去焦点时
    onAtrrachedToWindow() 当把该组件放入到某个窗口时
    onDetachedFromWindow() 当把该组件从某个窗口上分离时触发的方法
    onWindowVisibilityChanged(int): 当包含该组件的窗口的可见性发生改变时触发的方法
  • view的结构

Android系统的视图结构的设计也采用了组合模式,即View作为所有图形的基类,Viewgroup对View继承扩展为视图容器类。

Android来电播放铃声和接通停止铃声_自定义

自定义控件类

public class CallToggleButton extends View {

    private Bitmap backgroundBitmap;// 背景图
    private Bitmap slidBtn;// 可以滑动的图片
    private int backgroundWidth, slidBtnWidth;
    private Paint paint;//画笔
    private float slidBtn_left;// 滑动按钮的左边距
    private int firstX;// 手机按下的x坐标
    private int lastX;// 手机抬起的x坐标
    public myOnEventListener listener;

    public CallToggleButton(Context context) {
        super(context);
        initView();
    }

    public CallToggleButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

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

    private void initView() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        //获取按钮背景
        backgroundBitmap = BitmapFactory.decodeResource(getResources(),
                R.drawable.ldx_07_s480);
        options.inSampleSize = ScreenTools.calculateInSampleSize(options, 110,
                160); // 110,160:转换后的宽和高,具体值会有些出入
        options.inJustDecodeBounds = false;
        //获取滑动按钮图
        slidBtn = BitmapFactory.decodeResource(getResources(),
                R.drawable.ldx_03);

        paint = new Paint();
        //设置抗锯齿
        paint.setAntiAlias(true);

        backgroundWidth = backgroundBitmap.getWidth();
        slidBtnWidth = slidBtn.getWidth();

        slidBtn_left = (backgroundWidth / 2) - (slidBtnWidth / 2);
    }
    /*
     * 测量view宽高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        ScreenTools.init(getContext());
        // 设置宽高
        setMeasuredDimension(backgroundBitmap.getWidth(),
                backgroundBitmap.getHeight());
    }

    /*
     * 绘制当前view的内容
     */
    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
        canvas.drawBitmap(slidBtn, slidBtn_left, 0, paint);
    }
    /*
     * 滑动事件
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            firstX = lastX = (int) event.getX();
            break;
        case MotionEvent.ACTION_MOVE:
            // 计算手指移动的距离
            int dis = (int) event.getX();
            // 根据手指的位置,改变slidBtn_left的值
            slidBtn_left = dis;
            break;

        case MotionEvent.ACTION_UP:
            int maxLeft = backgroundWidth - slidBtnWidth;
            if (slidBtn_left >= maxLeft) {
                // 滑动到最右调用的方法
                listener.RightEvent();
            } else if (slidBtn_left < (slidBtnWidth / 2)) {
                // 滑动到最左调用的方法``
                listener.LeftEvent();
            } else {
                // 接听按钮回到原点
                Log.i("simple", "接听按钮回到原点");
                slidBtn_left = (backgroundWidth / 2) - (slidBtnWidth / 2);
            }
            break;
        }
        flushView();
        return true;
    }

    /**
     * 刷新当前视图
     */
    private void flushView() {
        int maxLeft = backgroundWidth - slidBtnWidth;
        // 确保 slideBtn_left >= 0
        slidBtn_left = (slidBtn_left > 0) ? slidBtn_left : 0;

        // 确保 slideBtn_left <=maxLeft
        slidBtn_left = (slidBtn_left < maxLeft) ? slidBtn_left : maxLeft;

        /*
         * 刷新当前视图调用invalidate 导致 执行onDraw执行
         */
        invalidate();
    }
    /**view事件方法*/
    public void setOnEvent(myOnEventListener listener){
        this.listener = listener;
    }
    /**view接口方法*/
    interface myOnEventListener{
        abstract void RightEvent();
        abstract void LeftEvent();
        }

MainActivity类

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

           CallToggleButton cb = (CallToggleButton)findViewById(R.id.toggleButton);
            cb.setOnEvent(new CallToggleButton.myOnEventListener() {
                @Override
                public void RightEvent() {
                    Log.i("simple","滑动到最右");
                    Toast.makeText(MainActivity.this,"滑动到最右",Toast.LENGTH_SHORT).show();
                }

                @Override
                public void LeftEvent() {
                    Log.i("simple","滑动到最左");
                    Toast.makeText(MainActivity.this,"滑动到最左",Toast.LENGTH_SHORT).show();
                }
            });
    }
}

布局文件

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <com.simple.togglebuttondemo.CallToggleButton
        android:id="@+id/toggleButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        />

</RelativeLayout>

Android来电播放铃声和接通停止铃声_自定义_02


Android来电播放铃声和接通停止铃声_android_03