전편은 여기
2012/04/12 - [Android Study] - Android Custom Widget 만들기 6편 

실전 사용 code
    // OnOffButtonActivity.java 내용
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        OnOffButton btn = (OnOffButton) findViewById(R.id.OnOffButton);
        btn.setOnButtonClickListener(new OnButtonClickListener() {
            @Override
            public void onResult(boolean onResult) {
                Toast.makeText(OnOffButtonActivity.this, "OnResult : " + onResult,
                       Toast.LENGTH_SHORT).show();
            }
        });
       // 초기 버튼을 off 상태로 설정
        btn.setOnOff(false);
    } 

    // main.xml 내용 
    // Widget class의 정확한 위치를 지정 해야 함
    <com.android.customwidget.OnOffButton
        android:id="@+id/OnOffButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/> 

이렇게 하고 나면 on off 상태 변경 혹은 animation 종료 시 toast 팝업이 발생 함.
후~ 이로써 custom widget은 끝은 아니고 일부 종료~ 

'Android' 카테고리의 다른 글

Android QR code  (0) 2014.08.12
Android AsyncTask 함정 카드  (1) 2014.08.03
Android Custom Widget 만들기 6편  (0) 2012.04.12
Android Custom Widget 만들기 5편  (0) 2012.04.12
Android Custom Widget 만들기 4편  (0) 2012.04.12
전편 필요한분 여기~
2012/04/12 - [Android Study] - Android Custom Widget 만들기 5편 

후 곧 마무리 지어 지을 수 있을듯.
 
    // 결과물 Listener에 전달 하는 함수
    private void onResult() {
       // Listener 객체가 null 이 아닐 경우만 호출
        if (mListener != null) mListener.onResult(mIsOn);
    }
    // Listener 등록 함수
    public void setOnButtonClickListener(OnButtonClickListener listener) {
        mListener = listener;
    }
    // on off toggle 함수
    public void toggleOnOff() {
        mHandler.sendEmptyMessage(ANIMATION_MESSAGE_START);
    }
    // on off setting 함수
    public void setOnOff(boolean isOn) {
        mIsOn = isOn;
       // 기본 값은 on 상태를 가정하고 설정
        int left = 0;
        int right = mMovementLimite;
       // off 상태 일때
        if (mIsOn == false) {
            left = mBtnWidth - mMovementLimite;
            right = mBtnWidth;
        }
       // button rect left, right 위치 지정
        mSource.left = left;
        mSource.right = right;
       // 움직일 delta 값 초기화 
        mMoveDelta = 0;
       // 화면 갱신
        invalidate();
    }
    // 현재 상태 얻어 오기 (on 이면 true)
    public boolean getIsOn() {
        return mIsOn;
    } 
    // Listener 등록을 위한 interface 함수
    public interface OnButtonClickListener {
       // On - Off 상태 변경되면 호출됨
        public abstract void onResult(boolean onResult);
    }
    // 저장된 instance restore 함수
    @Override
    protected void onRestoreInstanceState(Parcelable state) {
       // EXTRA_ON_OFF_SAVE_KEY 값으로 on off 저장된 instance 값 읽어 옴
       // EXTRA_ON_OFF_SAVE_KEY 는 string으로 아무 것이든 상관 없음 
        mIsOn = ((Bundle)state).getBoolean(EXTRA_ON_OFF_SAVE_KEY);
       // 움직일 delta 값 초기화 
        mMoveDelta = 0;
       // 기본 값은 on 상태를 가정하고 설정
        int left = 0;
        int right = mMovementLimite;
       // off 상태 일때
        if (mIsOn == false) {
            left = mBtnWidth - mMovementLimite;
            right = mBtnWidth;
        }
       // button rect가 null 일경우 새로 생성
        if (mSource == null) {
            mSource = new Rect(left, 0, right, mBtnHeight);
       // button rect가 null 이 아니면 left, right 위치 설정 
        } else {
            mSource.left = left;
            mSource.right = right;
        }
       // 기존에 저장되어 있는 state 부모 클래스에 에 전달
       // 기존 instance 정보는 EXTRA_SAVE_INSTANCE_KEY 사용
        super.onRestoreInstanceState(((Bundle)state).getParcelable(
         EXTRA_SAVE_INSTANCE_KEY));
    }
   // instance 저장 함수
    @Override
    protected Parcelable onSaveInstanceState() {
       // instance 저장 할 bundle 생성
        Bundle bundle = new Bundle();
       // EXTRA_SAVE_INSTANCE_KEY 사용 하여 기존 instance 저장
        bundle.putParcelable(EXTRA_SAVE_INSTANCE_KEY, super.onSaveInstanceState());
       // EXTRA_ON_OFF_SAVE_KEY 사용 하여 기존 on off 상태 저장  
        bundle.putBoolean(EXTRA_ON_OFF_SAVE_KEY, mIsOn);
       // bundle 전달
        return bundle;
    } 

실 사용 법은 담편에... 후~ 

'Android' 카테고리의 다른 글

Android AsyncTask 함정 카드  (1) 2014.08.03
Android Custom Widget 만들기 7편  (0) 2012.04.12
Android Custom Widget 만들기 5편  (0) 2012.04.12
Android Custom Widget 만들기 4편  (0) 2012.04.12
Android Custom Widget 만들기 3편  (0) 2012.04.12
전편은 여기에.
2012/04/12 - [Android Study] - Android Custom Widget 만들기 4편 

음 이제 Handler 하고 몇가지 함수? 하고 Listener만 설명 하면 될듯.
이번엔 덩치큰 Handler 부터... 
    // Button animation을 담당하는 handler
    private class ButtonMoveHandler extends Handler {
       // handler 에 message가 전달 되면 호출 되는 함수
        @Override
        public void handleMessage(Message msg) {
          // message 종류 구분
            switch (msg.what) {
          // message 가 animation 시작 일 때
            case ANIMATION_MESSAGE_START :
             // animation 구분 값은 ture
                mIsAnimation = true;
              // 현재 left 값을 얻어옴
                int left = mSource.left;
              // on 상태에서 시작 했다면
                if (mIsOn == true) {
                 // 움직일 delta 값이 양수 라면
                    if (mMoveDelta > 0) {
                    // MOVE_TO_RIGHT_LEFT 값 보다 크게 움직였을 경우
                    // MOVE_TO_RIGHT_LEFT 값은 80 
                        if (left < MOVE_TO_RIGHT_LEFT) {
                       // 오른쪽으로 animation 시작
                            this.sendEmptyMessage(ANIMATION_MESSAGE_MOVE_RIGHT);
                    // MOVE_TO_RIGHT_LEFT 값 보다 작게 움직였을 경우 
                        } else {
                       // 왼쪽으로 animation 시작
                            this.sendEmptyMessage(ANIMATION_MESSAGE_MOVE_LEFT);
                        }
                 // 움직일 delta 값이 음수 라면  
                    } else {
                    // 왼쪽으로 animation 시작  
                        this.sendEmptyMessage(ANIMATION_MESSAGE_MOVE_LEFT);
                    }
              // off 상태에서 시작 했다면  
                } else {
                 // animation 방향을 구분 하기 위한 최대 값 계산
                    int max = mBtnWidth - mMovementLimite - MOVE_TO_RIGHT_LEFT;
                 // 움직일 delta 값이 음수 라면  
                    if (mMoveDelta < 0) {
                     // left 값이 계산된 값 보다 크게 움직였을 경우
                        if (left > max) {
                        // 왼쪽으로 animation 시작  
                            this.sendEmptyMessage(ANIMATION_MESSAGE_MOVE_LEFT);
                     // left 값이 계산된 값 보다 작게 움직였을 경우  
                        } else {
                        // 오른쪽으로 animation 시작  
                            this.sendEmptyMessage(ANIMATION_MESSAGE_MOVE_RIGHT);
                        }
                 // 움직일 delta 값이 양수 라면  
                    } else {
                    // 오른쪽으로 animation 시작    
                        this.sendEmptyMessage(ANIMATION_MESSAGE_MOVE_RIGHT);
                    }
                }
                break;
          // message 가 animation left 이동 일 때  
            case ANIMATION_MESSAGE_MOVE_LEFT :
              // 이동 delta 값은 DURATION_VALUE와 같음 (한 스텝에 이동 할 거리)
              // DURATION_VALUE 는 13
                mMoveDelta = DULATION_VALUE;
              // onDraw 호출
                invalidate();
              // 다시 자기 자신 호출 (종료 될 때까지 반복 호출)
                this.sendEmptyMessage(ANIMATION_MESSAGE_MOVE_LEFT);
                break;
          // message 가 animation right 이동 일 때
            case ANIMATION_MESSAGE_MOVE_RIGHT :
              // 이동 delta 값은 - DURATION_VALUE와 같음 (한 스텝에 이동 할 거리)  
              // DURATION_VALUE 는 13  
                mMoveDelta = DULATION_VALUE * -1;
              // onDraw 호출  
                invalidate();
              // 다시 자기 자신 호출 (종료 될 때까지 반복 호출)  
                this.sendEmptyMessage(ANIMATION_MESSAGE_MOVE_RIGHT);
                break;
          // message 가 animation stop 일 때 
            case ANIMATION_MESSAGE_STOP :
              // animation flag false로 설정
                mIsAnimation = false;
              // 움직일 delta 값 0으로 설정 
                mMoveDelta = 0;
              // 화면 갱신을 위한 onDraw 호출 
                invalidate();
              // left, right 이동 animation handler message 삭제 
                this.removeMessages(ANIMATION_MESSAGE_MOVE_RIGHT);
                this.removeMessages(ANIMATION_MESSAGE_MOVE_LEFT);
              // Listener 를 호출 최종 결과 통보 
                onResult();
                break;
            }
        }
    } 

이로써 덩치 큰놈들은 죄다 설명 끝났음 후~ 아구 힘들다.
담편에는 가벼운 메소드 몇 개만 하면 끝날듯?

'Android' 카테고리의 다른 글

Android Custom Widget 만들기 7편  (0) 2012.04.12
Android Custom Widget 만들기 6편  (0) 2012.04.12
Android Custom Widget 만들기 4편  (0) 2012.04.12
Android Custom Widget 만들기 3편  (0) 2012.04.12
Android Custom Widget 만들기 2편  (0) 2012.04.12
이전글.. 필요한분 여기.
2012/04/12 - [Android Study] - Android Custom Widget 만들기 3편


남은 코드 이어서...
    // Touch 이벤트 처리 함수
   @Override
    public boolean onTouchEvent(MotionEvent event) {
       // touch 행동 (action) 얻기
        int action = event.getAction();
        switch (action) {
       // touch down 했을 때
        case MotionEvent.ACTION_DOWN :
          // mIsAnimation 은 boolean 객체 (animation 진행 상황 구분)
            if (mIsAnimation) mHandler.sendEmptyMessage(ANIMATION_MESSAGE_STOP);
          // int 형 X 좌표 저장 객체
            mOldPosition = (int) event.getX();
            break;
       // touch move 했을 때 
        case MotionEvent.ACTION_MOVE :
          // animation 중이라면 아무것도 안함
            if (mIsAnimation) return super.onTouchEvent(event);
          // animation 상태가 아니면 현재 좌표 읽어옴
            int current = (int) event.getX();
          // 현재 좌표와 예전 좌표의 차이가 TOUCH_POINT_GAP 보다 클때만 반응
          // TOUCH_POINT_GAP 값은 10
            if (Math.abs(mOldPosition - current) > TOUCH_POINT_GAP) { 
              // int형 변수 움직일 거리 저장
                mMoveDelta = mOldPosition - current;
              // 현재 좌표를 old 좌표에 복사
                mOldPosition = current;
              // onDraw() 호출 
                invalidate();
            }
            break;
       // touch cancel 되거나 up 했을때 
        case MotionEvent.ACTION_CANCEL :
        case MotionEvent.ACTION_UP :
          // animation이 동작 중이지 않다면 수행
            if (mIsAnimation == false) {
              // button 그림이 on 상태가 됬을때
                if (mSource.left == 0 && mMoveDelta < 0) {
                    mMoveDelta = 0;
                 // Listener 에다가 해당 event 전달
                    onResult();
              // button 그림이 off 상태가 됬을때
                } else if (mSource.right == mBtnWidth && mMoveDelta > 0) {
                    mMoveDelta = 0;
                 // Listener 에다가 해당 event 전달 
                    onResult();
              // 움직이던 도중 일때 
                } else {
                 // animation 동작하게 handler 호출 
                    mHandler.sendEmptyMessage(ANIMATION_MESSAGE_START);
                }
            }
            break;
        }
       // 나머지 다른 경우는 기존 code 유지
        return super.onTouchEvent(event);
    }
    // 그림 그리는 함수
    @Override
    protected void onDraw(Canvas canvas) {
       // animation 을 종료 해야 할지 구분 하는 변수
        boolean animetionStop = false;
       // left 위치 계산
        int left = mSource.left + mMoveDelta;
       // right 위치 계산  
        int right = mSource.right + mMoveDelta;
       // right 값이 오른쪽 끝일 경우
        if (right >= mBtnWidth) {
          // 더이상 이동 하지 못하게 left 값 고정
            left = mBtnWidth - mMovementLimite;
          // 더이상 이동 하지 못하게 right 값 고정 
            right = mBtnWidth;
          // off 상태로 변경
            mIsOn = false;
          // animation 동작 중이었으면 animation 종료
            if (mIsAnimation) animetionStop = true;
       // left 값이 왼쪽 끝일 경우 
        } else if (left <= 0) {
          // 더이상 이동 하지 못하게 left 값 고정  
            left = 0;
          // 더이상 이동 하지 못하게 right 값 고정  
            right = mMovementLimite;
          // on 상태로 변경
            mIsOn = true;
          // animation 동작 중이었으면 animation 종료  
            if (mIsAnimation) animetionStop = true;
        }
       // 이미지 rect의 left 값 설정
        mSource.left = left;
       // 이미지 rect의 right 값 설정
        mSource.right = right;
       // canvas에 bitmap 그림
        canvas.drawBitmap(mOnOffBitMap, mSource, mContent, new Paint()); 
        super.onDraw(canvas);
       // animation 종료 해야하면 handler 호출 
        if (animetionStop)  mHandler.sendEmptyMessage(ANIMATION_MESSAGE_STOP);
    } 

남은 코드는 다음 편에~ To be continue. 

'Android' 카테고리의 다른 글

Android Custom Widget 만들기 6편  (0) 2012.04.12
Android Custom Widget 만들기 5편  (0) 2012.04.12
Android Custom Widget 만들기 3편  (0) 2012.04.12
Android Custom Widget 만들기 2편  (0) 2012.04.12
Android Custom Widget 만들기 1편  (1) 2012.04.12
전편 필요한분 여기있음~
2012/04/12 - [Android Study] - Android Custom Widget 만들기 2편 

에구 삭신이야...
이제부터는 화면 그리는 것 까지는 어케 나오도록 해볼 예정임.
바로 코드 설명 갑니당.

  // 초기화 함수
  private void initializeOnOffButton() {
       // onTouch가 가능 하도록 설정
        this.setClickable(true);
       // boolean 변수 on off 상태 값이로 이용 
        mIsOn = true;
       // OnOff image bitmap (리소스에서 읽어옴) 
        mOnOffBitMap = BitmapFactory.decodeResource(
                                    getResources(), R.drawable.onoff_img);
       // int형 on off image bitmap 크기 
        mBtnHeight = mOnOffBitMap.getHeight();
        mBtnWidth = mOnOffBitMap.getWidth();
       // 화면 scale 얻어 오는 내용 (이미지가 풀 사이즈로 보이면 안됨)
        float fscale = getContext().getResources().getDisplayMetrics().density;
       // int형 변수 좌우로 움직일 수 있는 최대 크기 계산
       // 여기서
MAXIMUM_WIDTH_VALUE 는 187 임
        mMovementLimite = (int) (MAXIMUM_WIDTH_VALUE * fscale);
       // On 상태로 위치 조정
        int left = 0;
        int right = mMovementLimite;
       // OnOff image rect 변수 설정
        mSource = new Rect(left, 0, right, mBtnHeight);
       // Display 될 rect 변수 설정
        mContent = new Rect(0, 0, mMovementLimite/2, mBtnHeight/2);
       // Animation 효과를 주기 위한 handler
        mHandler = new ButtonMoveHandler();
    }

    // 화면 크기 계산 함수
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 현재 width의 mode 얻어 오기
       // fill_parent, match_parent, wrap_content... 
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        // width 크기 변수
        int widthSize = 0;
        // 현재 height의 mode 얻어 오기
       // fill_parent, match_parent, wrap_content... 
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        // height 크기 변수  
        int heightSize = 0;
        // 현재 모드에 따라 크기 결졍.
        switch(heightMode) {
            // 값이 고정일때 예(10dp)
            case MeasureSpec.UNSPECIFIED:
                heightSize = heightMeasureSpec;
                break;
            // wrap_content 일때
            case MeasureSpec.AT_MOST:
                heightSize = mBtnHeight/2;
                break;
            // fill_parent, match_parent 일때 
            case MeasureSpec.EXACTLY:
                heightSize = MeasureSpec.getSize(heightMeasureSpec);
                break;
        }
        // 현재 모드에 따라 크기 결졍.
        switch(widthMode) {
            // 값이 고정일때 예(10dp)  
            case MeasureSpec.UNSPECIFIED:
                widthSize = widthMeasureSpec;
                break;
            // wrap_content 일때  
            case MeasureSpec.AT_MOST:
                widthSize = mMovementLimite;
                break;
            // fill_parent, match_parent 일때 
            case MeasureSpec.EXACTLY:
                widthSize = MeasureSpec.getSize(widthMeasureSpec);
                break;
        }
        // 화면 크기 등록
        setMeasuredDimension(widthSize, heightSize);
    } 

흐아~ 지친당.
자 담편에서 봅세당 ㅎㅎ 

'Android' 카테고리의 다른 글

Android Custom Widget 만들기 5편  (0) 2012.04.12
Android Custom Widget 만들기 4편  (0) 2012.04.12
Android Custom Widget 만들기 2편  (0) 2012.04.12
Android Custom Widget 만들기 1편  (1) 2012.04.12
Android Study ListView Indexer 6편  (3) 2012.03.07
이전 글 필요한분 여기로. 
2012/04/12 - [Android Study] - Android Custom Widget 만들기 1편

OnOffButton 클래스는 View를 상속 받아 만들 예정임.
View 하고 ViewGroup 하고 둘중 하나를 가지고 custom widget을 많이 만드는듯 싶은데.
ViewGroup은 Widget(component)가 여러개 있는걸 컨트롤 할때 사용
단독 Widget(component)는 View를 사용함.

아래는 궁금하실 코드 내용 설명 @_@

// class를 만들고 View 클래스 상속 받으면 생성자 3개 종류중 1개를 꼭 써줘야함.
// 문제가 좀 있어서 3개다 사용 해주는 것이 좋음 

public class OnOffButton extends View {
    // Context만 가지고 만들어지는 생성자 (Activity등 클래스에서 new 해서 생성)
    public OnOffButton(Context context) {
       // 일일이 초기화 함수 호출하기도 아까우니 super를 this로 변경합세다.
        super(context);
       // context 만 있는 상태로 호출
       this(context, null, -1) 
    }
   // Context, AttributeSet 두가지로 만들어진 생성자 (Layout XML 파일에서 사용)
    public OnOffButton(Context context, AttributeSet attrs) {
       // 일일이 초기화 함수 호출하기도 아까우니 super를 this로 변경합세다. 
        super(context, attrs);
       // context, attributeset이 있는 상태로 호출 
        this(context,  attrs , -1) 
    }
   // Context, AttributeSet, Style 값까지 있는 생성자
   // Layout XML 파일에서 Thema 까지 지정 해줄때 사용 되는듯(정확한건 모름) 
    public OnOffButton(Context context, AttributeSet attrs, int defStyle) {
       // 다른 생성자 밑 모든 생성자가 최종적으로 부른는 녀석    
        super(context, attrs, defStyle);
       // 여기서 부터는 초기화 함수 호출 및 초기화 설정이 들어 갈 예정
       ... 
    }
   // Widget (component) 크기 계산 함수 파라메터는 화면 크기에 대한 정보
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
   // 사용자 Touch 이벤트에 대한 함수 파라메터는 이벤트 값(좌표, 행동)이 전달됨
    @Override
    public boolean onTouchEvent(MotionEvent event) { 
       return super.onTouchEvent(event);
    }
   // Widget을 그리는 함수 파라메터는 현재 그릴 canvas
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}

이정도가 완전 기본 뼈대 코드임.
빠르게 담편으로... 

'Android' 카테고리의 다른 글

Android Custom Widget 만들기 4편  (0) 2012.04.12
Android Custom Widget 만들기 3편  (0) 2012.04.12
Android Custom Widget 만들기 1편  (1) 2012.04.12
Android Study ListView Indexer 6편  (3) 2012.03.07
Android Study ListView Indexer 5편  (0) 2012.03.07


아이폰을 보다보면 On Off 버튼 쪼기 조것을 많이 사용 하는데, 왠지 멋있어 보여서. Android 용으로 아이폰과 비슷(?) 하게 동작 하는 custom widget을 만들어 보고 싶었음. 그냥 그렇다구.

Custom widget 이라고 해봐야 별거 없고 그냥 만들어 보면 됨 (안될라나?)

시작하게 된다면 나름 생각 있는 프로그래머? 라면 대충 View 혹은 ViewGroup을 상속 받아서 만들려고 시도 할꺼임? 내말과 다르면 별수 없고...

나는 View 상속 받아서 만들꺼임. 나도 잘 모르고 혹 잘 따라오신다면 나 보다 더많은걸 건져 갈 수 있을지도... 움헤헤헤


난 이미 얼추 다만들어 놨기때문에 대충 내 플젝 상태는 이러함.

프로젝트 네임 OnOffButton, 패키지명 com.android.customwidget 뭐 이정도면 될듯.

참고로 그림 한장이 필요한데 아이폰에 있는 on off button 그림 이게 필요함.

우앙 댑따 크다~ ㅋㅋ 준비물 끝... 담편으로 고고씽~

'Android' 카테고리의 다른 글

Android Custom Widget 만들기 3편  (0) 2012.04.12
Android Custom Widget 만들기 2편  (0) 2012.04.12
Android Study ListView Indexer 6편  (3) 2012.03.07
Android Study ListView Indexer 5편  (0) 2012.03.07
Android Study ListView Indexer 4편  (0) 2012.03.07

+ Recent posts