State_checked не включает и отключает просмотр изображений
Предварительный просмотр Android Studio 2.0
Здравствуйте,
У меня есть этот селектор, который подключен к imageview
. Я хочу включить и выключить imageview
. Таким образом, отобразится зеленый цвет и на дисплее будет отображаться красный цвет.
Однако, когда я нажимаю кнопку imageview
, ничего не происходит. Я пробовал разные комбинации state_pressed и state_checked. И теперь его становится слишком запутанным. Что мне здесь не хватает.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:drawable="@drawable/bottom_left_border"/>
<item android:state_checked="true"
android:drawable="@drawable/bottom_left_border_pressed">
</item>
</selector>
Большое спасибо за любые предложения,
Ответы
Ответ 1
Однако, когда я нажимаю изображение, ничего не происходит.
Итак, как сказал @Zielony, причина проста: ImageView
не поддерживается проверенные состояния.
Каждый класс, расширенный из View
, поддерживает разные состояния: нажатие, выделение, сфокусированное, проверяемое (обратите внимание, что не проверено состояние) и т.д. Но проверено - это особое состояние. И лишь немногие View
поддерживают его: ToggleButton
, Switch
, RadioButton
, CheckBox
, CheckedTextView
. Они реализовали интерфейс Checkable
.
У вас есть варианты решения вашего дела, но это зависит от того, что именно вам нужно:
-
Если вам действительно нужна эта простая вещь
Таким образом, выкл. будет отображать зеленый цвет и на дисплее будет отображаться красный цвет.
вы можете использовать CheckBox
или CheckedTextView
, например. Просто создайте селектор:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="<red_color>" android:state_checked="true" />
<item android:drawable="<green_color>" />
</selector>
и используйте его
<CheckBox
android:layout_width="50dp"
android:layout_height="50dp"
android:text=""
android:button="@null"
android:clickable="true"
android:background="<your_selector>"/>
-
Используйте другое состояние. Вы можете использовать state_activated
(или state_selected
, но будьте осторожны, потому что выбранное свойство переходного процесса)
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="<red_color>" android:state_activated="true" />
<item android:drawable="<green_color>" />
</selector>
и переключить это состояние с помощью кода
<your_image_view>.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
<your_image_view>.setActivated(!<your_image_view>.isActivated());
}
});
-
Напишите свой собственный проверяемый класс. Вы можете видеть от других людей, как это сделать:
-
Официальная реализация Android из старого приложения для контактов
public class CheckableImageView extends ImageView implements Checkable {
private boolean mChecked;
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
public CheckableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
public void toggle() {
setChecked(!mChecked);
}
public boolean isChecked() {
return mChecked;
}
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}
}
-
Другая реализация в MultiChoiceAdapter
-
Реализация с OnCheckedChangeListener
и сохраненным состоянием, например CheckBox
class, а также это лучшая реализация, которую я когда-либо видел
public class CheckableImageView extends ImageView implements Checkable {
private static final int[] checkedStateSet = { android.R.attr.state_checked };
private boolean mChecked = false;
private OnCheckedChangeListener mOnCheckedChangeListener;
private boolean mBroadcasting;
public CheckableImageView(Context context) {
super(context);
}
public CheckableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CheckableImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public boolean performClick() {
toggle();
return super.performClick();
}
@Override
public void toggle() {
setChecked(!mChecked);
}
@Override
public int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, checkedStateSet);
}
return drawableState;
}
@Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
// Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting) {
return;
}
mBroadcasting = true;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
mBroadcasting = false;
}
}
/**
* Register a callback to be invoked when the checked state of this button
* changes.
*
* @param listener the callback to call on checked state change
*/
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
mOnCheckedChangeListener = listener;
}
/**
* Interface definition for a callback to be invoked when the checked state
* of a compound button changed.
*/
public static interface OnCheckedChangeListener {
/**
* Called when the checked state of a compound button has changed.
*
* @param buttonView The compound button view whose state has changed.
* @param isChecked The new checked state of buttonView.
*/
void onCheckedChanged(CheckableImageView buttonView, boolean isChecked);
}
static class SavedState extends BaseSavedState {
boolean checked;
/**
* Constructor called from {@link CompoundButton#onSaveInstanceState()}
*/
SavedState(Parcelable superState) {
super(superState);
}
/**
* Constructor called from {@link #CREATOR}
*/
private SavedState(Parcel in) {
super(in);
checked = (Boolean) in.readValue(null);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeValue(checked);
}
@Override
public String toString() {
return "CheckableImageView.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " checked=" + checked + "}";
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.checked = isChecked();
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChecked(ss.checked);
requestLayout();
}
}
Эти варианты, которые приходят на ум во-первых и имеют хорошую реализацию. Но вы также можете придумать свои собственные версии или использовать простые переменные для сохранения состояния и переключения вручную, как сказал Чираг-Савсани, но в этом случае вам придется отказаться от использования selector
s.
Ответ 2
Причина очень проста - ImageView вообще не проверяет наличие state_checked. Комментарий от @frank-n-stein наиболее близок к ответу на этот вопрос.
У вас есть два варианта:
- используйте представление с поддержкой state_checked (например, CheckBox)
- Добавить state_checked в ImageView
Чтобы добавить поддержку state_checked, вам нужно реализовать интерфейс Checkable. Вот так:
public class CheckableImageView extends ImageView implements Checkable {
private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
private boolean mChecked;
... constructors
@Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void toggle() {
setChecked(!mChecked);
}
@Override
public boolean performClick() {
toggle();
return super.performClick();
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
@Override
protected Parcelable onSaveInstanceState() {
SavedState result = new SavedState(super.onSaveInstanceState());
result.checked = mChecked;
return result;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setChecked(ss.checked);
}
protected static class SavedState extends BaseSavedState {
protected boolean checked;
protected SavedState(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(checked ? 1 : 0);
}
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
private SavedState(Parcel in) {
super(in);
checked = in.readInt() == 1;
}
}
}
Код отсюда: https://github.com/shomeser/AndroidLayoutSelector/blob/master/LayoutSelector/src/main/java/com/example/layoutselector/CheckableLinearLayout.java
Ответ 3
Здравствуйте, я также использую этот сценарий в своем текущем приложении.
1) Использование CheckBox
Используйте CheckBox
с свойством android:button="@null"
,
Это свойство удалит границу CheckBox
и отобразит только ваши изображения с возможностью рисования.
state_checked
свойство будет работать с CheckBox
<CheckBox
android:id="@+id/imgDisplayCheckimg"
android:layout_width="wrap_contenrt"
android:layout_height="wrap_contenrt"
android:background="@drawable/display_checkbox"
android:button="@null"
android:checked="false"
android:clickable="true" />
Это графический файл
display_checkbox.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- When selected, use red-->
<item android:drawable="@drawable/red_color" android:state_checked="true"/>
<!-- When not selected, use green-->
<item android:drawable="@drawable/green_color" android:state_checked="false"/>
</selector>
Замените red_color и green_color своим назначаемым именем.
2) Используя ImageView
Объявить эту переменную глобально
boolean switchStatus = false;
Найдите свой ImageView и добавьте ниже Click Listener.
switchImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(switchStatus == true) {
anonymousImage.setImageResource(R.drawable.red);
switchStatus = false;
} else {
anonymousImage.setImageResource(R.drawable.green);
switchStatus = true;
}
}
});
ImageView
в файле макета.
<ImageView
android:id="@+id/switchImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/green" />
Измените имя на зеленый и красный с помощью вашего имени.
Ответ 4
Вы можете попробовать:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected ="false"
android:drawable="@drawable/bottom_left_border"/>
<item android:state_selected ="true"
android:drawable="@drawable/bottom_left_border_pressed">
</item>
</selector>
И код Java:
imageview.setImageDrawable(getBaseContext().getResources().getDrawable(R.drawable....));
//set the click listener
imageview.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
v.setSelected(!v.isSelected());
//other code if need
}
});
Ответ 5
Подумайте о том, чтобы переключить ваш образ на кнопку, поскольку state_checked
не влияет на изображение.
Затем установите фон кнопки на свой selector_xml
<Button>
...
android:background="@drawable/your_selector_xml"
</Button>
Ответ 6
Попробуйте этот
< < < < < < Первый путь → → →
1. Создайте color.xml в папке "values" в папке "res", если она уже создана, создайте ее с каким-то другим именем: color.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<drawable name="red">#FF0000</drawable>
<drawable name="green">#00FF00</drawable>
<drawable name="blue">#0000FF</drawable>
</resources>
2. Теперь создайте селектор, например on_off_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:drawable="@drawable/red" />
<item android:state_pressed="true" android:drawable="@drawable/green"/> </selector>
3. Теперь установите свойство "android: background" вашего ImageView примерно таким же, как и для параметра android: clcikable = "true" :
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:clickable="true"
android:id="@+id/imageView"
android:background="@drawable/on_off_selector"
/>
< < < < < < < Второй путь → → → >
Сделать файл в папке с возможностью переноса on_off_selecor.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<color android:color="#FF0000" />
</item>
<item android:state_pressed="true">
<color android:color="#00FF00" />
</item>
<item>
<color android:color="#FF0000" />
</item>
</selector>
Теперь установите свойство "android: background" вашего ImageView, что-то вроде этого также установите android: clcikable = "true" :
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:clickable="true"
android:id="@+id/imageView"
android:background="@drawable/on_off_selector"
/>