Android 사용자 정의 컨트롤 스위치 단추 학습 노트 공유

오늘 은 사용자 정의 단일 컨트롤 에 대해 서 말씀 드 리 겠 습 니 다.스위치 버튼 을 가지 고 말씀 드 리 겠 습 니 다.이런 것 을 많이 보 셨 을 거 라 고 믿 습 니 다.먼저 효 과 를 보 겠 습 니 다.

우 리 는 흔히 볼 수 있 는 스위치 버튼 을 볼 수 있다.그러면 분석 해 보 자.
우선:
이것 은 두 장의 그림 으로 구성 되 어 있다.
① 열 리 고 닫 히 는 배경 그림
② 열 림 과 닫 기 를 제어 하기 위 한 미끄럼 버튼
첫 번 째 단계:
클래스 계승 View 를 쓰 고 몇 가지 방법 을 다시 쓰 십시오.
첫 번 째 는 구조 함수 입 니 다.매개 변수의 함수 와 두 매개 변수의 함 수 를 다시 쓰 면 됩 니 다.두 매개 변수의 함수 가 사용자 정의 속성 을 사용 할 수 있 기 때 문 입 니 다.
두 번 째 는 컨트롤 의 크기 를 제어 하 는 C>proctected void onMeasure(int width MeasureSpec,int height MeasureSpec){}
세 번 째 는 컨트롤 을 그 리 는 방법 C>proctected void onDraw(Canvas canvas){}
두 번 째 단계:
사용자 가 지정 한 두 장의 그림 을 불 러 옵 니 다.사용자 정의 속성 을 사용 하여 불 러 옵 니 다.values 디 렉 터 리 에 새 attrs.xml 를 만 들 고 xml 파일 에 사용자 정의 속성 이름과 사용자 정의 속성의 필드 와 값 형식(즉 배경 그림 과 슬라이더 그림)을 지정 하면 됩 니 다.

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="switchView_attrs">
    <attr name="background" format="reference"></attr>
    <attr name="slide" format="reference"></attr>
  </declare-styleable>  
</resources>

각 필드 의 의 미 는 여기 서 말 하지 않 겠 습 니 다.모 르 는 것 은 앞의 몇 편 을 보 세 요.잘 쓰 면 구조 함수 에 불 러 오기 만 하면 됩 니 다.

public SwitchView(Context context, AttributeSet attrs) {
    super(context, attrs);
    //       
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.switchView_attrs);
    //         
    Drawable switchBackground = ta.getDrawable(R.styleable.switchView_attrs_background);
    Drawable switchView_slide = ta.getDrawable(R.styleable.switchView_attrs_slide);
    //          
    backgroundBitmap = convertDrawable2BitmapSimple(switchBackground);
    switchSlide = convertDrawable2BitmapSimple(switchView_slide);
  }
그러나 주의해 야 할 것 은:
사용자 정의 속성 에서 찾 은 것 은 Drawable 대상 이 고 우리 가 원 하 는 것 은 Bitmap 대상 이기 때문에 우 리 는 먼저 Drawable 대상 을 Bitmap 대상 으로 바 꿔 야 합 니 다.사실은 여러 가지 방법 이 있 습 니 다.여기 서 가장 간단 한 방법 을 소개 합 니 다.BitmapDrawable 류 를 통 해:

// Drawable  Bitmap
  public Bitmap convertDrawable2BitmapSimple(Drawable drawable) {
    BitmapDrawable bd= (BitmapDrawable)drawable;
    return bd.getBitmap();
  }
세 번 째 단계:
onMeasure 방법 으로 컨트롤 의 크기 를 조절 할 수 있 습 니 다.이 스위치 버튼 의 크기 는 배경 크기 만큼 크 고 배경 크기 로 만 설정 할 수 있 습 니 다.

//       
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (backgroundBitmap != null) {
      //            
      setMeasuredDimension(backgroundBitmap.getWidth(), backgroundBitmap.getHeight());
    }else {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
  }
네 번 째 단계:
이 스위치 단 추 는 클릭 이나 이동 을 통 해 컨트롤 의 개폐 와 닫 기 를 제어 해 야 하기 때문에 onTouch Event 방법 을 실현 해 야 합 니 다.물론 세 가지 이벤트 가 발생 해 야 합 니 다.누 르 고 이동 하 며 들 어 올 릴 때 클릭,이동 또는 들 어 올 릴 때마다 다시 그 려 야 합 니 다.슬라이더 의 상태 가 어떤(네 가지 상태 가 있어 야 합 니 다)처음에 기본 상태 가 비어 있 는 지 분석 해 보 겠 습 니 다.
1.클릭 할 때
2.이동 할 때
3.들 때
4.비 었 을 때(즉 아무것도 하지 않 았 을 때)
먼저 클릭 할 때의 상황 을 분석 합 니 다.
① 누 르 거나 움 직 이 는 좌표 가 슬라이더 너비 의 절반 이상 일 때 슬라이더 를 오른쪽으로 이동
② 누 르 거나 움 직 이 는 좌표 가 슬라이더 너비 의 절반 이하 일 때 슬라이더 가 움 직 이지 않 는 다.
주:슬라이더 가 배경 밖으로 이동 하 는 것 을 방지 합 니 다.최대 슬라이더 오른쪽 과 배경 오른쪽 정렬(즉,최대 왼쪽 에서 배경 너비-슬라이더 너비)

다시 한 번 이동 할 때의 상황 을 보면 클릭 할 때 와 같 을 것 이다.
다시 들 어 올 릴 때의 상황 을 분석한다.
① 스위치 상태 가 켜 져 있 으 면 슬라이더 를 오른쪽으로 이동
② 스위치 상태 가 꺼 져 있 으 면 슬라이더 를 왼쪽으로 이동
그럼 언제 열 린 상태 와 닫 힌 상태 인지 어떻게 판단 하나 요?
① 들 어 올 린 좌표 가 배경 너비 의 절반 이상 일 때 열 린 상태 로 설정
② 들 어 올 린 좌 표 는 배경 너비 좌표 의 절반 이하 일 때 닫 힌 상태 로 설정

다시 한 번 빈 곳 을 분석 해 보면 들 었 을 때의 상황 과 같다 는 것 을 알 수 있다.
다섯 번 째 단계:
onDraw 방법 에서 배경 과 슬라이더 를 그립 니 다.방금 onTouchEvent 방법 을 분 석 했 는데 이번 에는 똑 같 습 니 다.슬라이더 의 네 가지 상 태 를 각각 처리 하고 앞의 onTouchEvent 방법 에서 슬라이더 의 상태 가 바 뀌 었 습 니 다.그리고 invalidate()방법 을 통 해 시스템 에 다시 그 리 는 것 을 알 립 니 다.
여섯 번 째 단계:
이 사용자 정의 컨트롤 을 만 드 는 것 은 사용자 가 사용 할 수 있 도록 하 는 것 입 니 다.지금 은 아무 소 용이 없습니다.사용자 가 사용 할 수 없 기 때문에 모니터 를 설정 하여 외부 에 인 터 페 이 스 를 제공 할 수 있 습 니 다.

/** 
   * switchView      
   * 
   * */
  interface OnSwitchChangedListener {
    public void onSwitchChange(boolean isOpen);
  }
  /** 
   *    switchView     
   * */
  public void setOnChangeListener(OnSwitchChangedListener listener) {
    switchListener = listener;
  }
이 모니터 의 boolean 값 은 할당 이 필요 합 니 다.언제 할당 할 까요?올 리 거나 비 어 있 을 때 할당 해 야 합 니 다.그 때 는 스위치 버튼 이 열 렸 는 지 닫 혔 는 지 확인 할 수 있 기 때 문 입 니 다.
일곱 번 째 단계:
이 단 계 는 레이아웃 파일 에서 사용자 정의 컨트롤 을 정의 하 는 데 사 용 됩 니 다.

<com.example.custom.SwitchView
    minguo:background="@drawable/switch_background"
    minguo:slide="@drawable/slide_button_background"
    android:id="@+id/switchView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>



정 의 된 View 를 사용 하면 모두 사용 할 수 있 을 것 입 니 다.아 닙 니 다.'안 드 로 이 드 개발 노트 의 사용자 정의 조합 컨트롤'을 보 세 요.
핵심 코드:
레이아웃 파일

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:minguo="http://schemas.android.com/apk/res/com.example.custom"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.example.custom.MainActivity" >
  <com.example.custom.SwitchView
    minguo:background="@drawable/switch_background"
    minguo:slide="@drawable/slide_button_background"
    android:id="@+id/switchView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
</LinearLayout>
사용자 정의 보기:SwitchView.자바

/**
 *        
 * @author Administrator
 *
 */
public class SwitchView extends View {
  //         
  private Bitmap backgroundBitmap,switchSlide;
  //  
  private Paint paint;
  //   x  (  、  、  )
  private float currentX;
  //            
  private boolean isOpen = false;
  //           
  private OnSwitchChangedListener switchListener;
  //       
  public static final int STATE_DOWN = 1; //     
  public static final int STATE_MOVE = 2; //     
  public static final int STATE_UP = 3;  //     
  public static final int STATE_NONE = 0; //    (         )
  //    (      )
  private int state = STATE_NONE;
  public SwitchView(Context context) {
    super(context,null);
  }
  public SwitchView(Context context, AttributeSet attrs) {
    super(context, attrs);
    //       
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.switchView_attrs);
    //         
    Drawable switchBackground = ta.getDrawable(R.styleable.switchView_attrs_background);
    Drawable switchView_slide = ta.getDrawable(R.styleable.switchView_attrs_slide);
    //          
    backgroundBitmap = convertDrawable2BitmapSimple(switchBackground);
    switchSlide = convertDrawable2BitmapSimple(switchView_slide);
  }
  // Drawable  Bitmap
  public Bitmap convertDrawable2BitmapSimple(Drawable drawable) {
    BitmapDrawable bd = (BitmapDrawable)drawable;
    return bd.getBitmap();
  }
  //       
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (backgroundBitmap != null) {
      //            
      setMeasuredDimension(backgroundBitmap.getWidth(), backgroundBitmap.getHeight());
    }else {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
  }
  //       
  @Override
  protected void onDraw(Canvas canvas) {
    //             
    if (backgroundBitmap != null) {
      paint = new Paint();
      //           Bitmap
      //       Bitmap         
      //       Bitmap         
      //         
      canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
    }
    switch (state) {
    case STATE_DOWN:    //             ,       
    case STATE_MOVE:
      //                       
      if (currentX > switchSlide.getWidth()/2f) {
        //       (         )
        float left = currentX - switchSlide.getWidth()/2f;
        //          ,              (           -    )
        float maxLeft = backgroundBitmap.getWidth() - switchSlide.getWidth();
        if (left > maxLeft) {
          left = maxLeft;
        }
        canvas.drawBitmap(switchSlide, left, 0, paint);
      //                      
      }else if (currentX < switchSlide.getWidth()/2f) {
        //         
        canvas.drawBitmap(switchSlide, 0, 0, paint);
      }
      break;
    case STATE_NONE:    //                 
    case STATE_UP:
      //              ,           
      if (isOpen) {
        if (switchListener != null) {
          switchListener.onSwitchChange(true);
        }
        canvas.drawBitmap(switchSlide, 
            backgroundBitmap.getWidth() - switchSlide.getWidth(), 0, paint);
      //             ,           
      }else {
        if (switchListener != null) {
          switchListener.onSwitchChange(false);
        }
        canvas.drawBitmap(switchSlide, 0, 0, paint);
      }
      break;
    default:
      break;
    }
  }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
      currentX = event.getX();
      //            
      state = STATE_DOWN;
      //          
      invalidate();//    
//     postInvalidate();//    
      break;
    case MotionEvent.ACTION_MOVE:
      currentX = event.getX();
      //           
      state = STATE_MOVE;
      invalidate();
      break;
    case MotionEvent.ACTION_UP:
      currentX = event.getX();
      //           
      state = STATE_UP;
      //                      
      if (currentX > backgroundBitmap.getWidth()/2f) {
        //     ,  
        isOpen = true;
      //                         
      }else if (currentX < backgroundBitmap.getWidth()) {
        //     ,  
        isOpen = false;

      }
      invalidate();
      break;
    }
    return true;
  }
  /** 
   * switchView      
   * 
   * */
  interface OnSwitchChangedListener {
    public void onSwitchChange(boolean isOpen);
  }
  /** 
   *    switchView     
   * */
  public void setOnChangeListener(OnSwitchChangedListener listener) {
    switchListener = listener;
  }
}

MainActivity.java

public class MainActivity extends Activity {

  private SwitchView switchView;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    switchView = (SwitchView) findViewById(R.id.switchView);
    switchView.setOnChangeListener(new OnSwitchChangedListener() {
      @Override
      public void onSwitchChange(boolean isOpen) {
        if (isOpen) {
          //          
          Toast.makeText(MainActivity.this, "     ", Toast.LENGTH_LONG).show();
        }else {
          //          
          Toast.makeText(MainActivity.this, "     ", Toast.LENGTH_LONG).show();
        }
      }
    });
  }
}

여러분 들 은 이렇게 간단 해 보 입 니 다.하 나 는 이렇게 많이 썼 습 니 다.사실은 우리 가 이것 을 배 우 는 것 은 이것 을 쓰기 위해 서가 아니 라 이것 보다 좋 은 기원 이 많은 것 은 이런 사고 와 사 고 를 배우 기 위해 서 입 니 다.여러분 들 은 빨리 해 보 세 요!
읽 어 주 셔 서 감사합니다. 저희 의 더 많은 멋 진 내용 도 계속 지 켜 봐 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기