마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

버튼 비활성화 질문입니다

0 추천
버튼이 다수인데 무엇이눌렸을때 다른 버튼을 비활성화 시키고싶은데요

액티비티 클래스 열고 상단에 멤버로 Button btn1,btn2,btn3 를 놓고 Create 때  findViewById 로 각각 핸들을 넣어주고

OnClick 에서 view.getId() 로 판별후 btn1에 해당하는게 눌렸을때

btn2.setEnabled 나 setClickable 로 제어하면 btn2 를 비활성화/활성화 할수 있는게 아닌건지 비활성화가 안됩니다

매개변수인 view 를 이용하려면 현재 눌린 버튼의 view라서 현재 눌린버튼 외의 버튼을 제어하려면 어떻게 해야하는지

조언을 구합니다..
숭늉 (540 포인트) 님이 2014년 7월 23일 질문
숭늉님이 2014년 7월 23일 수정

3개의 답변

+1 추천
 
채택된 답변

레이아웃

activity_main.xml

<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="com.example.buttondisabletest.MainActivity" >

    <Button
        android:id="@+id/btn_0"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:text="Button1" />

    <Button
        android:id="@+id/btn_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btn_0"
        android:layout_centerHorizontal="true"
        android:text="Button2" />

    <Button
        android:id="@+id/btn_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btn_1"
        android:layout_centerHorizontal="true"
        android:text="Button3" />

</RelativeLayout>

 

 

 

 

액티비티

MainActivity.java

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends ActionBarActivity implements View.OnClickListener {
	private static final int BUTTON_COUNT = 3;
	private View[] mButtons;

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

		mButtons = new Button[BUTTON_COUNT];
		final String format = "btn_%d";
		for (int i = 0; i < BUTTON_COUNT; i++) {
			int id = getResources().getIdentifier(String.format(format, i), "id", getPackageName());
			mButtons[i] = findViewById(id);
			mButtons[i].setOnClickListener(this);
		}

	}

	@Override
	public void onClick(View v) {
		doWork(v.getId() - R.id.btn_0);
	}

	private void doWork(int position) {
		if (flagWorking) {
			return;
		}
		for (int i = 0; i < BUTTON_COUNT; i++) {
			mButtons[i].setEnabled(i == position);
		}
		flagWorking = true;
		new MyTask().execute(position);
	}

	private boolean flagWorking = false;

	private class MyTask extends AsyncTask<Integer, Void, Void> {

		@Override
		protected Void doInBackground(Integer... params) {
			Log.v(getClass().getSimpleName(), "works while 3 sec... position: " + params[0]);
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Log.v(getClass().getSimpleName(), "finished work. " + params[0]);
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);
			flagWorking = false;
			for (int i = 0; i < BUTTON_COUNT; i++) {
				mButtons[i].setEnabled(true);
			}
		}
	}
}

 

칠리님 (10,910 포인트) 님이 2014년 7월 23일 답변
숭늉님이 2014년 7월 23일 채택됨
깔끔한 코드와 함께 3초 딜레이까지 적용해주셨네요!

그런데 파일읽는 문제 등때문에 연달아 안눌리게 하고 싶다고 하셔서 필요한것은 ProgressDialog등을 사용해서 해당 작업이 실행되고 있는 동안 다른 작업 못하게 막는 방법이 좋지 않나 생각합니다.
일단 파일 2번 엑세스 하는 문제가 추정시간 500ms 이상의 오래걸리는 작업인지 아닌지 몰라서...

그리고 제가.. 캔슬 불가능한 프로그레스 다이얼로그 극 혐오자라...

프로그레스 다이얼로그가 필요할 정도의 긴 작업이면 물론 사용하는게 맞다고 생각됩니다. 다른 작업을 못하게 하는것 보다는 현재 작업을 캔슬 할 수 있도록 하구요...
이런사태가 발생하지 않으려면 설계가 중요하죠 뭐 ^^;
맞는 말씀입니다.. ㅠㅠ
0 추천

제어하려는 모든 버튼을 배열에 담아서 멤버로 가지고 계시구요.

리스너는 단일 객체로 모두 셋팅하세요.

리스너의 onClick에서 멤버 버튼 배열을 루프 돌고 파라메터인 view와 같다면 enabled, 다르다면 disabled 하세요.

ex)

@Override
public void onClick(View view){
        int size = mButtons[i].length;
        for(int i = 0; i < size; i++){
                view.setEnabled(view == mButtons[i]);
        }
}

 

칠리님 (10,910 포인트) 님이 2014년 7월 23일 답변
답변 감사합니다만 이것도 안되는데요.. 원래 되야되는거 아닌가요 ㅠ
되는게 맞는건데요...
clickable은 단순히 클릭만 안되게...
enabled는 상태 자체를 비활성 시켜 StateListDrawable까지 적용되도록 ...
btn1을 눌르면 btn1 이 mButtons[0] 이라면 true가 됐다가 나머진 루프끝까지 false 이기땜에 view, 현재눌린 btn1이 enable 됐다가 그뒤에 size만큼 횟수로 disable 되는게아닌가요?
죄송합니다....
mButtons[i].setEnabled(view == mButtons[i]);
전 지금 테스트 하니까 눌린거 외에 모두 잘 disabled됩니다...
어라 그럼 제가 아까말한대로인데요 배열만 안넣었을뿐이지 저도
멤버로 핸들들을 놔뒀고 if(view.getId() == btn1){  btn2.setEnabled(fasle);  //할일들 하고 btn2.setEnabled(true); } 이런식으로 생각했는데 안되더라구요 무슨 차이죠?
헐? view.getId() == btn1 ㅠㅠㅠㅠㅠㅠㅠ
view.getId는 이 뷰의 res id를 반환하구요...
btn1.getId와 비교하셔야 합니다...
아니면 R.id.btn1 과 같이 리소스 아이디랑...
btn1은 객체니까... int인 아이디랑 비교하시면 안됩니다...
프리컴파일에서 빨간불 들어오지 않았나요?
테스트 코드 답변에 새로 달았는데 다른점 찾아보시겠어요?...
아 알아보기쉬우시라고 그런건데 getId() 는 리소스.아이디랑비교했구요
지금봤네요 코드한번 보겠습니다 감사합니다
0 추천
하신대로 하는게 맞는 방법입니다.

그런데 활성화/비활성화가 어떤 의미인지요

버튼 눌러졌을 때 동작을 안하면 되는건지. 안보여야 하는건지.

 

동작문제라면 각 버튼마다 clickListener를 따로 만들어서 null값등으로 제어해도 될듯하고요.

내용을 보면 ClickListener를 implements 하신거같은데  view.getId() 체크 할 때 Flag값들을 설정해서 동작을 막으면 되고요

아님 setVisibility(View.INVISIBLE)로 아예 안보이게 하면 될거같습니다.
q1212 (26,020 포인트) 님이 2014년 7월 23일 답변
버튼이 있는데 이게 빨리 두개를 연달아 누르면 파일을 읽고 그런거기땜에 btn1이 눌리고 나서 일정시간동안 btn2 가 눌러지지않게하려고합니다 clickListener 를 사용하구요 view.getId 해서 기능을 나눠주었는데
그게 부족합니다 if( view.getId() == btn1){  // 이안에서 btn2 를 못누르게 했다가 풀어주고싶습니다
}
...