Thay thế hình ảnh chọn theo chương trình


116

Tôi có một ImageView có tài nguyên hình ảnh có thể vẽ được đặt thành bộ chọn. Làm cách nào để tôi lập trình truy cập vào bộ chọn và thay đổi hình ảnh của trạng thái được tô sáng và không được tô sáng?

Đây là một mã của bộ chọn:

<?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>

Tôi muốn có thể thay thế btn_icon_hlbtn_iconvới các hình ảnh khác.


Sẽ dễ dàng hơn để có hai bộ chọn và trao đổi chúng?
bigstones

2
Vấn đề với điều đó là bạn có thể kết thúc với hàng trăm tệp xml.
Emile

Câu trả lời:


244

Theo như tôi đã có thể tìm thấy (tôi đã thử làm một cái gì đó tương tự), không có cách nào để sửa đổi một trạng thái sau khi StateListDrawable đã được xác định. Tuy nhiên, bạn có thể xác định một cái MỚI thông qua mã:

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);

Và bạn chỉ có thể giữ hai trong số chúng trong tay, hoặc tạo một cái khác khi bạn cần.


1
Tôi không thể thêm cái này vào chế độ xem hình ảnh. setState không có sẵn trên đó.
giọtOfJupiter

2
thực sự tôi đã tìm thấy nó, setImageDrawable () Cảm ơn bạn rất nhiều vì nó đã hoạt động và tiết kiệm cho tôi khoảng 40 tệp xml!
giọtOfJupiter

2
Vì vậy, tôi có một lưu ý liên quan đến điều này. Tôi đã hy vọng bạn có thể trả lời. Tôi có bộ chọn này được đặt trên ImageView nằm trong Điều khiển tùy chỉnh. Điều khiển tùy chỉnh cũng có một bộ chọn làm nền. Vì vậy, bộ chọn của toàn bộ điều khiển hoạt động, trong khi bộ chọn ImageView thì không. Có điều gì tôi đang làm sai? Có một trình tự?
giọtOfJupiter

1
Không có gì! Vâng, tôi không biết tại sao tôi đặt setState, nên là setImageDrawable, bạn đã đúng. Theo câu hỏi khác của bạn, tôi khuyên bạn nên đăng một câu hỏi mới với mã cho điều khiển tùy chỉnh và bộ chọn của nó, tôi không chắc câu trả lời cho câu hỏi đó.
Kevin Coppock

3
tôi đang sử dụng cùng một mã. luôn luôn là hình ảnh mà tôi đã chỉ định trong trạng thái ----> new int [] {}. tôi đã sai ở đâu ??
KK_07k11A0585

6

Tôi đã có cùng một vấn đề và tiến thêm một bước để giải quyết nó. Tuy nhiên, vấn đề duy nhất là bạn không thể chỉ định NavStateListDrawable trong xml, vì vậy bạn phải đặt nền của phần tử UI thông qua mã. Phương thức onStateChange sau đó phải được ghi đè để đảm bảo rằng mỗi khi mức độ của bản vẽ chính được thay đổi, bạn cũng cập nhật cấp độ của danh sách cấp độ con.

Khi xây dựng NavStateListDrawable, bạn phải vượt qua cấp độ của biểu tượng bạn muốn hiển thị.

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;
    }
}

Đối với tất cả các trạng thái có thể vẽ nút điều hướng khác nhau, tôi có một cái gì đó như sau.

<?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>

Tôi sẽ đăng bài này dưới dạng câu hỏi và câu trả lời, nhưng khi bạn hỏi chính câu hỏi đó, bạn sẽ đến đây. Lưu ý, điều này giúp bạn tiết kiệm rất nhiều định nghĩa tệp xml. tôi đã giảm từ khoảng 50-100 xml định nghĩa xuống còn khoảng 4!.


Mã navstatelistdrawable có hiệu quả làm cho bộ chọn xml trở nên dư thừa.
Emile

Xin chào emilie, Có khả năng có thể rút ra làm nền nút không xuất hiện lần đầu tiên vì bất kỳ lý do gì. Hiện tại tôi đang gặp vấn đề khi cần chạm vào khu vực của nút để nền hiển thị hoặc tắt và chuyển trở lại hoạt động. (Điều này chỉ xảy ra trên màn hình hdpi, nhưng hoạt động tốt trên mdpi của tôi). Tôi tin rằng những người khác có thể có vấn đề này quá. Là mã của bạn được kiểm tra cho tất cả các mật độ màn hình?
ryvianstyron

Xin chào, không, điều này đã được viết một cách công bằng khi trở lại và chỉ dành cho một thiết bị tại thời điểm đó. Tôi không chắc loại vấn đề nào có thể phát sinh mặc dù theo như tôi biết nhiều mật độ màn hình và bố cục không nên có vấn đề.
Emile

Cảm ơn tôi hoàn toàn không biết mình đã làm gì sai nhưng cuối cùng tôi chỉ có những điều sau: buttonStates = new StateListDrawable (); buttonStates.addState (new int [] {statePression}, ApplicationConstants.moduleImageLoader.findImageByName (drawable_pressed)); buttonStates.addState (new int [] {- ​​stateF Focused, -statePression, -stateSelected}, ApplicationConstants.moduleImageLoader.findImageByName (drawable_n normal));
ryvianstyron

1
Đây là nơi đầu tiên tôi thấy rằng các giá trị âm phải được sử dụng cho các trạng thái được đặt thành false. Các tài liệu không rõ ràng về nó. Cảm ơn vì tiền hỗ trợ!
eocanha
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.