본문 바로가기

PROGRAMING/Android

slide touch button , 알람에 ,월,화,수,목,금,토, 슬라이드 터치.(drag touch)

알람 어플을 만들때

월,화,수,목,금,토,일 버튼이 있고 이것을 살짝 slid로 드래그 하면 버튼들이 눌리는 그런 것을

구현 하고 싶었다. 


Touch이벤트를 이용해서 쉽게 구현할수 있을 것 이라 생각했지만 실상은 그렇지 않았다.

버튼 마다 Touch이벤트를 구현했지만 한버튼 예를 월 버튼을 클릭하고 slide를 하여

화 버튼까지 간다고 하여도 화 버튼의 touch 이벤트는 반응 하지 않았다.

-- ACTION_DOWN이벤트가 오고 나서  ACTION_MOVE 이벤트는 버튼 사이를 인식 하지 못하였다.


구글 검색 결과 

http://stackoverflow.com/questions/5073617/slide-finger-into-buttons-android

boolean firstTime = true;   //버튼이 한번 클릭하고 난 다음에 다시 실행하지 않게 해주는 변수

OnTouchListener testTouchListener = new OnTouchListener(){

public boolean onTouch(View v, MotionEvent me){

Rect r = new Rect();

secondButton.getDrawingRect(r);

if(r.contains((int)me.getX(),(int)me.getY())){   //버튼 1의 클릭 이벤트에서 버튼 2를 감지

//Log.i(myTag, "Moved to button 2");

if(firstTime == true){

firstTime = false;

secondButton.performClick();

}

}

if(me.getAction() == MotionEvent.ACTION_UP){

 //When we lift finger reset the firstTime flag

firstTime = true;

}

return false;

}

};

firstButton.setOnTouchListener(testTouchListener);  //버튼 1의TouchListener 등록

와 같은 내용을 찾을수 잇었지만 실제로 구현을 하다가 좌표 값이 상이해서 다른 방법을 찾아보았다.

위 방법은 포기


위 내용 중 버튼이 한번 클릭 하는 로직을 참고, 또한 Touch 이벤트 확인을 버튼이 아닌

버튼을 감싸고 있는 LinearLayout 에서 하도록 하려는 생각을 하게 되었다.


LInearLayout을 상속 받는 CustomLinearLayout을 생성하여 TouchListener를 등록하고 좌표를 구해보았지만

LinearLayout의 자식 버튼들 ,월,화,수,...버튼 위에서는 좌표값을 구할수 없었다.


그래서 찾던 중 dispatchTouchEvent함수에서는 자식 버튼 위에 position이 위치하여도 정상적으로 좌표값이 나타나는 것을 확인하였다.

그래서 LinearLayout을 상속 받아 구현한 LinearLayoutCustom.java와 ImageButton을 상속받아서 구현한 ImageButtonCustom을 코딩했다.

LinearLayoutCustom.java

public class LinearLayoutCustom extends LinearLayout {

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

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

public LinearLayoutCustom(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }

@Override

public boolean dispatchTouchEvent(MotionEvent ev) {

boolean ret =super.dispatchTouchEvent(ev);

Log.i("TEXT222","dispatchTouchEvent  LinearLayoutCustom ret : " +ret);

clickChildToogleButton(ev);

return ret;

}

private void clickChildToogleButton(MotionEvent ev){

Log.i("TEXT222","clickChildToogleButton ev : " +ev);

if(ev.getAction()==MotionEvent.ACTION_DOWN ){

for(int i=0;i<this.getChildCount();i++){

if(this.getChildAt(i) instanceof ImageButtonCustom){

ImageButtonCustom bb=(ImageButtonCustom)this.getChildAt(i);

bb.releaseFirstClick();   //버튼이 DOWN되었을때 자식 버튼들이 한번 클릭되도록 상태변수를 초기화하는 함수를 실행한다.

}

}

}

if(ev.getAction()==MotionEvent.ACTION_MOVE){

for(int i=0;i<this.getChildCount();i++){

if(this.getChildAt(i) instanceof ImageButtonCustom){

this.getChildAt(i).getX();

float cX =this.getChildAt(i).getX();

float cY =this.getChildAt(i).getY();

float cW =this.getChildAt(i).getWidth();

float cH =this.getChildAt(i).getHeight();

Log.i("TEXT222","clickChildToogleButton this.getChildAt("+i+").getX() :"+ cX);

Log.i("TEXT222","clickChildToogleButton this.getChildAt("+i+").getY() :"+ cY);

Log.i("TEXT222","clickChildToogleButton this.getChildAt("+i+").getWidth() :"+ cW);

Log.i("TEXT222","clickChildToogleButton this.getChildAt("+i+").getHeight() :"+ cH);

if(  (cX<=ev.getX()) && (ev.getX()<=(cX+cW))   &&  (cY<=ev.getY()) && (ev.getY()<=(cY+cH)) ){

Log.i("TEXT222","clickChildToogleButton  -------- this.getChildAt("+i+") click  --------  ");

ImageButtonCustom bb=(ImageButtonCustom)this.getChildAt(i);

bb.performClick(); //현재 위치가 자식의 ImageButton에 위치한다면 performClick실행

}

}

}

}

}

}

LinearLayoutCustom의 자식들중 ImageButtonCustom이 있고 그 좌표에 현재 ACTION_MOVE좌표가 있다면 performClick으로 click이벤트를 호출한다.


ImageButtonCustom.java


public class ImageButtonCustom extends android.widget.ImageButton {

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

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

public ImageButtonCustom(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); }

protected volatile boolean firstClick = true;

@Override

public boolean performClick() {

Log.i("TEXT","performClick firstClick : "+firstClick);

if(firstClick) {                           //버튼이 중복 클릭이 안되게 한다.

firstClick =false;

return super.performClick();

return false;

}

public void releaseFirstClick(){    //버튼이 클릭되록 설정하는 초기화 함수.

firstClick=true;

}

}


ImageButtonCustom에서는 firstClick 변수를 두어 performClick이 한번 호출되면 다음에 같은 좌표에 있더라도 호출이 안되게 끔 한다.


위와 같이 구현하고 실제사용하는 

MainActivity.java

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

iv1[0] = (ImageButtonCustom) findViewById(R.id.imageView1);

iv1[1] = (ImageButtonCustom) findViewById(R.id.imageView2);

iv1[2] = (ImageButtonCustom) findViewById(R.id.imageView3);

iv1[3] = (ImageButtonCustom) findViewById(R.id.imageView4);

iv1[4] = (ImageButtonCustom) findViewById(R.id.imageView5);

iv1[5] = (ImageButtonCustom) findViewById(R.id.imageView6);

iv1[6] = (ImageButtonCustom) findViewById(R.id.imageView7);

for(int i=0;i<iv1.length;i++){

    iv1[i].setTag("unPress");             //테스트 어플에서 눌림을 구분하는 구분자

iv1[i].setBackgroundColor(Color.GREEN); //눌림을 구분하는 색상

}

for(int i=0;i<iv1.length;i++){

iv1[i].setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

String tmp = (String)v.getTag();

if(tmp.equals("unPress")){

v.setTag("Press");

v.setBackgroundColor(Color.RED);

} else if(tmp.equals("Press")) {

v.setTag("unPress");

v.setBackgroundColor(Color.GREEN);

}

}

});

}

}


결과 -- 정상동작



예제 파일

ImageTouch.zip