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

다른 레이아웃에 있는 버튼을 비활성화 할 수 있나요?

0 추천
제가 레이아웃이 2개 있는데

A레이아웃에서 1번 버튼을 눌러
B레이아웃으로 들어갑니다

 

이때 B레이아웃에서 맞는 번호를 입력하면
다시 A레이아웃으로 보내고

제가 눌렀던 A레이아웃의 1번 버튼을 비활성화 하고 싶습니다

 

지금 1번 버튼으로 A 에서  B레이아웃 전환

B레이아웃에서 맞는 번호 입력 후 다시 A레이아웃으로 전환까진 구현했습니다

B레이아웃에서 번호 입력 후 다시 A레이아웃으로 왔을 때

A레이아웃의 1번 버튼을 비활성화 할 수 있나요?

intent로 값 받아오는것도 텍스트밖에 안해봐서 버튼자체를 받아 올 수 있을까요?

 

요약 : 레이아웃에서 동작한 결과로 인해  다른 레이아웃의 버튼을 비활성화 할 수 있나요?

만약 비활성화가 된다면 다시 활성화 하는 방법도 부탁드리겠습니다...
까비슨 (160 포인트) 님이 2022년 5월 16일 질문

3개의 답변

+1 추천
 
채택된 답변

문제를 다시 읽어보니 퀴즈 앱을 만드시는가 보네요. 아래에 간단한 예제코드를 첨부합니다.

// 예약번호를 입력받기 위한 새로운 액티비티 선언. B클래스에 해당.
public class BookingNoActivity extends AppCompatActivity {

    // Intent에 사용할 상수갑 선언. 아무 문자열이나 정의하면 됨.
    public static final String EXTRA_ROOM_NO ="roomNo";

    // 뷰멤버 필드. 님이 이렇게 사용하고 있다고 가정함.
    private EditText bookingNoEdt;
    private Button submitBtn;

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

        setupViews();
    }

    private void setupViews() {
        bookingNoEdt = findViewById(R.id.bookingNoEdt); // 예약번호
        submitBtn = findViewById(R.id.submitBtn);
        submitBtn.setOnClickListener(v -> {
            submitBookingNo();
        });
    }

    // 이전 액티비티로 결과값을 Intent에 담아 저장.
    private void submitBookingNo() {
       //입력값이 없을 때 처리
       // if (getBookingNo().isEmpty()) {
       //    return;
       // }

        int result = expectedRoomNoEntered() ? Activity.RESULT_OK : Activity.RESULT_CANCEL;

        Intent intent = new Intent();
        setResult(result);
        this.finish();
    }

   private boolean expectedRoomNoEntered() {
      return expectedRoomNo().equals(getBookingNo();
   }

   private String expectedRoomNo() {
          return getIntent().getStringExtra(EXTRA_ROOM_NO, "");
   }

   private String getBookingNo() {
       return bookingNoEdt.getText().toString();
   }
}

 

AnswerActivity를 띄우는  Activity입니다.

// A클래스에 해당하는 액티비티
public class RoomListActivity extends AppCompatActivity {

    private Button bookingNoBtn;

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

        setupViews(); 
    }

   // BookingNoActivity를 띄울 ActivityREsultLauncher 인스턴스
   // registerForActivityResult는 이미 액티비티에 존재하는 API이므로 메소드형태는 소스를 확인하기 바람.
   // 여기서는 소스를 간결하게 작성하기위해 람다식을 사용함. 
   private final ActivityResultLauncher<String> getBookingNo = registerForActivityResult(new GetAnswer(),
           isExpectedRoomNo -> {
                if (isExpectedRoomNo)
                     expectedRoomNoEntered();
            });

    private void setupViews() {
         bookingNoBtn = findViewById(R.id.bookingNoBtn);
         bookingNoBtn.setOnClickListener(view -> {
             getBookingNo.launch(getRoomNo());
        });
    }
    
   // 원하는 예약번호 입력이 완료되었을 경우 처리
    private void expectedRoomNoEntered() {
        // TODO: 원하는 처리를 이곳에 작성     
    }

   private String getRoomNo() {
        // TODO: 필요한 코드 작성
    }
}

 

// 예약번호를 받을 액티비티를 띄우고 결과값을 파싱하는 컨트랙 클래스 작성.
// 멤버메소드를 잘 보면 startActivityForResult에 createIntent()메소드가 사용되고 
// onActivityResult의 역할을 하는 콜백에 parseResult가 사용됨을 알 수 있음.
public class GetBookingNo extends ActivityResultContract<String, Boolean> {
    // 예약번호입력 액티비티를 띄울 때 사용할 Intent를 작성. 예약번호입력 액티비티에 입력받아야 방번호를 넘김.
    @NonNull
    @Override
    public Intent createIntent(@NonNull Context context, String input) {
        Intent intent = new Intent(context, BookingNoActivity.class);
        intent.putExtra(EXTRA_ROOM_NO, input);
        return intent;
    }

    // 예약번호입력 액티비티에서 결과값이 넘어올 때 어떻게 값을 읽어올 것인지 작성.
    // 엑약번호입력 액티비티에서 맞는 방번호를 입력했는지 체크하고 있으므로 resultCode = Activity.RESULT_OK인 경우만 처리하면 됨.
    @Override
    public Boolean parseResult(int resultCode, @Nullable Intent intent) {
       return resultCode == Activity.RESULT_OK;
    }
}

 

입력값을 넘기고 validation을 하는 부분은 RoomActivity에서 할 수도 있고 BookingNoActivity에서 할 수도 있습니다. 님의 상황에 따라 저절한 위치를 선택하세요.

 

spark (225,780 포인트) 님이 2022년 5월 16일 답변
까비슨님이 2022년 5월 20일 채택됨
제가 구현하려고 한 건 제가 설정해놓은 번호로 자리 예약하기 어플이었습니다.
그래서 그런지 몰라도 예제를 봐도 잘모르겠습니다.
A레이아웃(좌석선택창)에서 1번 좌석(버튼)을 선택 시
B레이아웃(번호입력창)이 켜지고
B레이아웃에서 제가 지정해놓은 전화번호를 맞게 입력하면
A레이아웃으로 돌아오면서 A레이아웃에서
제가 선택한 1번 버튼이 비활성화 되는것을 구현하고 싶습니다...
살려주세요...
그리고 먼저 처음으로 해준 답변에선
GetResult는 새로 선언해야 하는 자바 클래스인가요? 아니면
//A에 입력해주면 되는건가요?
제가 올려드린 샘플코드나 님이 원하는 거나 업무는 다르지만 님이 원하는 바는 똑같습니다.
사용자 입력을 받아서 입력값에 따라 처리하는 거요.
GetResult는 새로운 자바 클래스이구요, 해당 개발자 문서를 보시고 구글에서 예제를 검색해서 샘플코드를 찾아보셨을 때 전혀 이해가 가지 않으시면, 먼저 자바랑 안드로이드 기초를 좀 더 공부하셔야할 것 같은데요. 이 상태로는 제가 설명을 더 드려도 받아드리기가 쉬워보이지 않아요.... 일단 주석을 좀 달아놓을게요. 그래도 전혀 이해가 가지 않으시면 자바와 안드로드이 의 기본적인 코드에 익숙하지 않으신거예요. 그럴경우는 그 쪽부터 해결하세요.
0 추천

질문이 약간 명확하지 않습니다.질문의 내용에 있는 레이아웃은 액티비티나 프레그먼트로 보이네요. 레이아웃은 화면은 디자인할 때 사용하는 XML파일일 뿐 화면단위와는 상관이 없습니다. 

액티비티를 사용하느냐 프레그먼트를 사용하느냐에 따라 답이 달라지게 됩니다. 액티비티를 기준으로 말씀드리면, A에서 B를 호출할 때 startActivtiyForResult를 사용하여 모달방식(B에서 값을 전달받을 수 있는 형태)으로 띄워줍니다.

// A
private static final int REQUEST_CODE = 1000; //아무 int값이나 사용할 수 있음.

Intent intent = new Intent(A.this,    B.class);
startActivityForResult(intent , REQUEST_CODE);

A에서는 B에서 값을 받을 때 onActivityResult라는 콜백을 이용해서 처리하게 됩니다.
 

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);

            if (requestCode == REQUEST_CODE) {
                setButtonEnabled(resultCode  != RESULT_OK);
            }

 }

 

B에서는 입력이 끝나면 처리가 되었음을 저장한 후 종료합니다.
 

//B
setResult(RESULT_OK);
finish();

 

참고로 최근에 이 방식은 deprecated가 되었고 새로운 API가 도입이 되었습니다. 이 부분은 개발자 문서를 통해 확인하시기 바랍니다.

https://developer.android.com/training/basics/intents/result

 

public class GetResult extends ActivityResultContract<Void, Boolean> {
    @NonNull
    @Override
    public Intent createIntent(@NonNull Context context, @NonNull Void input) {
        return new Intent(context, B.class);
    }

    @Override
    public Boolean parseResult(int resultCode, @Nullable Intent result) {
        return resultCode == Activity.RESULT_OK;
    }
}


// B
ActivityResultLauncher<Void> mGetResult = registerForActivityResult(new GetResult(),
    new ActivityResultCallback<Boolean>() {
        @Override
        public void onActivityResult(Boolean isOk) {
            setButtonEnabled(!isOk);
        }
});


@Override
public void onCreate(@Nullable savedInstanceState: Bundle) {
    // ...

    Button selectButton = findViewById(R.id.select_button)
    selectButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            mGetResult.launch(null);
        }
    });
}

 

spark (225,780 포인트) 님이 2022년 5월 16일 답변
spark님이 2022년 5월 16일 수정
0 추천
Jetpack 의 Bus를 이용하면 쉽게 해결되실 듯 한데요 B에서 번호를 맞게 하였을대 Bus이벤트를 태우고 버튼 비활성화 처리하면 될거라고 생각됩니다
익명사용자 님이 2022년 5월 16일 답변
혹시 Jackpack Bus가 뭘 말씀하시는 건가요?
아.... event bus 입니다
검색하면 나오는 것들이 있으니 찾아보시면 되구요

다른걸로는 mvvm으로 viewmodel을 이용하면 A와 B 레이아웃에 공통사용 viewmodel을 통해 해결 할 수 있겠구요
참고로 EventBus는 한두개의 이벤트 정도에 사용하는데는 별 문제가 없으나 많이 사용해서 문제가 생길 경우 디버깅을 어렵게 만드는 관계로 적극적으로 사용하는 걸 권장하지 않습니다.  안드로이드 커뮤니티에서는 이벤트버스에 대한 언급이 거의 사라지고 없어요.
...