프로그래밍 방식으로 선택기 이미지 바꾸기


116

드로어 블 이미지 리소스가 선택기로 설정된 ImageView가 있습니다. 선택기에 프로그래밍 방식으로 액세스하고 강조 표시된 상태와 강조 표시되지 않은 상태의 이미지를 변경하려면 어떻게해야합니까?

다음은 선택기 코드입니다.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/iconSelector">
  <!-- pressed -->
  <item android:state_pressed="true" android:drawable="@drawable/btn_icon_hl" />
  <!-- focused -->
  <item android:state_focused="true" android:drawable="@drawable/btn_icon_hl" />
  <!-- default -->
  <item android:drawable="@drawable/btn_icon" />
</selector>

다른 이미지 로 교체 btn_icon_hl하고 싶습니다 btn_icon.


두 개의 선택기를 가지고 바꾸는 것이 더 쉬울까요?
bigstones

2
문제는 수백 개의 xml 파일로 끝날 수 있다는 것입니다.
Emile

답변:


244

내가 찾을 수있는 한 (나도 비슷한 것을 시도해 보았습니다) StateListDrawable이 이미 정의 된 후에는 단일 상태를 수정할 방법이 없습니다. 그러나 코드를 통해 새로운 것을 정의 할 수 있습니다.

StateListDrawable states = new StateListDrawable();
states.addState(new int[] {android.R.attr.state_pressed},
    getResources().getDrawable(R.drawable.pressed));
states.addState(new int[] {android.R.attr.state_focused},
    getResources().getDrawable(R.drawable.focused));
states.addState(new int[] { },
    getResources().getDrawable(R.drawable.normal));
imageView.setImageDrawable(states);

그리고 그 중 두 개를 손에 들고 있거나 필요에 따라 다른 것을 만들 수 있습니다.


1
이미지보기에 이것을 추가 할 수 없었습니다. setState를 사용할 수 없습니다.
dropsOfJupiter 2011 년

2
실제로 나는 그것을 찾았습니다, 그것의 setImageDrawable () 그것이 일하고 약 40 xml 파일을 저장해 주셔서 대단히 감사합니다!
dropsOfJupiter

2
그래서 이것에 대한 또 다른 관련 메모가 있습니다. 나는 당신이 대답 할 수 있기를 바랐습니다. 사용자 지정 컨트롤 내부에있는 ImageView에이 선택기가 설정되어 있습니다. 사용자 지정 컨트롤에는 배경으로 선택기가 있습니다. 따라서 전체 컨트롤의 선택기는 작동하지만 ImageView 선택기는 작동하지 않습니다. 내가 뭘 잘못하고 있니? 시퀀스가 있습니까?
dropsOfJupiter 2011 년

1
천만에요! 그래 내가 왜 setState를 넣었는지 모르겠지만 setImageDrawable이어야합니다. 맞습니다. 다른 질문에 따라 사용자 지정 컨트롤 및 해당 선택기에 대한 코드와 함께 새 질문을 게시하는 것이 좋습니다. 그에 대한 답변이 확실하지 않습니다.
Kevin Coppock 2011 년

3
동일한 코드를 사용하고 있습니다. 항상 ----> new int [] {} 상태에서 지정한 이미지가 유지됩니다. 내가 틀린 곳?
KK_07k11A0585

6

나는 같은 문제가 있었고 그것을 해결하기 위해 한 걸음 더 나아갔습니다. 그러나 유일한 문제는 xml에서 NavStateListDrawable을 지정할 수 없으므로 코드를 통해 UI 요소의 배경을 설정해야한다는 것입니다. 그런 다음 기본 드로어 블의 수준이 변경 될 때마다 하위 수준 목록의 수준도 업데이트되도록 onStateChange 메서드를 재정의해야합니다.

NavStateListDrawable을 구성 할 때 표시하려는 아이콘의 수준을 전달해야합니다.

public class NavStateListDrawable extends StateListDrawable {

    private int level;

    public NavStateListDrawable(Context context, int level) {

        this.level = level;
        //int stateChecked = android.R.attr.state_checked;
        int stateFocused = android.R.attr.state_focused;
        int statePressed = android.R.attr.state_pressed;
        int stateSelected = android.R.attr.state_selected;

        addState(new int[]{ stateSelected      }, context.getResources().getDrawable(R.drawable.nav_btn_pressed));
        addState(new int[]{ statePressed      }, context.getResources().getDrawable(R.drawable.nav_btn_selected));
        addState(new int[]{ stateFocused      }, context.getResources().getDrawable(R.drawable.nav_btn_focused));

        addState(new int[]{-stateFocused, -statePressed, -stateSelected}, context.getResources().getDrawable(R.drawable.nav_btn_default));


    }

    @Override
    protected boolean onStateChange(int[] stateSet) {

        boolean nowstate = super.onStateChange(stateSet);

        try{
            LayerDrawable defaultDrawable = (LayerDrawable)this.getCurrent();


            LevelListDrawable bar2 =  (LevelListDrawable)defaultDrawable.findDrawableByLayerId(R.id.nav_icons);
            bar2.setLevel(level);
        }catch(Exception exception)
        {

        }

        return nowstate;
    }
}

모든 다른 탐색 버튼 드로어 블 상태에 대해 다음과 같은 것이 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

   <item android:drawable="@drawable/top_bar_default" >

   </item>

    <item android:id="@+id/nav_icons" android:bottom="0dip">
        <level-list xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:maxLevel="0" >
                <bitmap
                    android:src="@drawable/top_bar_icon_back"
                    android:gravity="center" />
            </item>
            <item android:maxLevel="1" >
                <bitmap
                    android:src="@drawable/top_bar_icon_nav"
                    android:gravity="center" />
            </item>
            <item android:maxLevel="2" >
                <bitmap
                    android:src="@drawable/top_bar_icon_settings"
                    android:gravity="center" />
            </item>
            <item android:maxLevel="3" >
                <bitmap
                    android:src="@drawable/top_bar_icon_search"
                    android:gravity="center" />
            </item>
        </level-list>

    </item>

</layer-list>

나는 이것을 질문과 대답으로 게시하려고했지만, 당신이 바로 그 질문을 한 것처럼 보았습니다. 여기 있습니다. 이것은 많은 xml 파일 정의를 저장합니다. 나는 약 50-100 개의 xml 정의에서 약 4!로 내려 갔다.


navstatelistdrawable 코드는 선택기 xml을 효과적으로 중복시킵니다.
Emile

안녕하세요 emilie, 버튼 배경으로 드로어 블이 어떤 이유로 처음으로 표시되지 않을 가능성이 있습니까? 현재 배경이 표시되도록 버튼 영역을 터치하거나 스위치를 끄고 활동으로 다시 전환해야하는 문제가 발생합니다. (이것은 hdpi 화면에서만 발생하지만 내 mdpi에서는 잘 작동합니다). 다른 사람들도이 문제가있을 수 있다고 생각합니다. 코드가 모든 화면 밀도에 대해 테스트됩니까?
ryvianstyron

안녕, 아니, 이것은 공정하게 쓰여졌 고 당시 하나의 장치에만 해당되었습니다. 여러 화면 밀도와 레이아웃이 문제를 일으키지 않아야한다는 것을 알고 있지만 어떤 종류의 문제가 발생할 수 있는지 잘 모르겠습니다.
Emile 2012

고마워요 내가 뭘 잘못하고 있는지 잘 모르겠지만 결국 다음과 같이했습니다. buttonStates = new StateListDrawable (); buttonStates.addState (new int [] {statePressed}, ApplicationConstants.moduleImageLoader.findImageByName (drawable_pressed)); buttonStates.addState (new int [] {-stateFocused, -statePressed, -stateSelected}, ApplicationConstants.moduleImageLoader.findImageByName (drawable_normal));
ryvianstyron 2012

1
이것은 false로 설정된 상태에 대해 음수 값을 사용해야하는 첫 번째 장소입니다. 문서는 그것에 대해 명확하지 않습니다. 팁 고마워!
eocanha
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.