How to change the custom preference layout's imageview programmatically?

Viewed 1806

I used settings activity to let a user select from different resources in my android app. All preference items are checkbox. I've defined a custom layout for each preference and connect it to the checkbox. When I click the preference item it is working properly but I can't understand at which position the preference is. So I want to change the imageview of the custom layout programmatically when I click on the preference item. Is there a way to do that?

Below, the second item is the default text, I want to change the layout to the first one. Everything is working but I want to change the plus image to another image programmatically when I click on this item (to understand that it is checked). Since this is settings activity, I couldn't find a way (there is no findviewbyid etc..) Android behaves the whole custom layout as a checkbox (you can click anywhere on the line)

Snapshot of the Settings

Settings.xml

<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">

    <CheckBoxPreference
        android:layout="@layout/source_item"
        android:key="gundem_haberturk"
        android:title="@string/haberturk"
        android:defaultValue="false"/>

</PreferenceScreen>

Custom Layout.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/layout_source_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/iv_source_logo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxWidth="100dp"
        android:maxHeight="40dp"
        android:src="@drawable/logo_haberturk"/>

    <TextView
        android:id="@+id/tv_source_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Habertürk"
        android:textSize="22sp"
        android:textStyle="bold" />

    <ImageView
        android:id="@+id/iv_source_selector"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:src="@drawable/checkbox_unchecked"/>

</RelativeLayout>

Settings Fragment:

public class GundemSettingsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle bundle, String rootKey) {

        addPreferencesFromResource(R.xml.gundem_settings);
    }
}

Settings Activity:

public class GundemSettingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_gundem_settings);
        Toolbar toolbar = findViewById(R.id.settings_toolbar);
        setSupportActionBar(toolbar);

        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }
    }   
}

Settings Activity xml

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   tools:context="com.example.hhs.haberler.Settings.GundemSettingsActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/settings_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <fragment
        android:layout_marginTop="?attr/actionBarSize"
        android:id="@+id/settings_fragment"
        android:name="com.example.haberler.Settings.GundemSettingsFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.design.widget.CoordinatorLayout>
1 Answers

You can create a custom Preference which extends from CheckBoxPreference and use it just like the CheckBoxPreference:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <your.package.name.CustomCheckBoxPreference
        android:layout="@layout/custom_checkbox_preference"
        android:key="custom_checkbox_pref"
        android:title="CustomCheckBoxPreferenceTitle"
        android:defaultValue="false"/>
</PreferenceScreen>

Please note that according to the documentation for the android:layout atttribute one has to use specific resource id's for the layout's root ViewGroup as well as the TextViews for title and summary. This will ensure that the customized Preference behaves just like any stock Preference.

By overriding onBindViewHolder(PreferenceViewHolder) you can "find" the ImageView and assign it to a corresponding field ivSourceSelector. And by overriding setChecked() you can swap the drawables when the checked state of the Preference changes.

Having said that, here's the code for CustomCheckBoxPreference:

public class CustomCheckBoxPreference extends CheckBoxPreference {

    private ImageView ivSourceSelector;

    public CustomCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public CustomCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public CustomCheckBoxPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomCheckBoxPreference(Context context) {
        super(context);
    }

    @Override
    public void setChecked(boolean checked) {
        super.setChecked(checked);
        if(ivSourceSelector != null) {
            ivSourceSelector.setImageResource(getResourceId(checked));
        }
    }

    @Override
    public void onBindViewHolder(PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);
        ivSourceSelector = holder.itemView.findViewById(R.id.iv_source_selector);
        if(ivSourceSelector != null){
            ivSourceSelector.setImageResource(getResourceId(isChecked()));
        }
    }

    private int getResourceId(boolean checked) {
        return checked ? R.drawable.custom_checkbox_checked : R.drawable.custom_checkbox_unchecked;
    }
}
Related