org.solovyev.android.prefs.MultiSelectListPreference Maven / Gradle / Ivy
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: [email protected]
* Site: http://se.solovyev.org
*/
package org.solovyev.android.prefs;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.preference.ListPreference;
import android.preference.Preference;
import android.util.AttributeSet;
import org.solovyev.android.view.R;
import org.solovyev.common.text.StringCollections;
import org.solovyev.common.text.StringMapper;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* A {@link Preference} that displays a list of entries as
* a dialog and allows multiple selections
*
* This preference will store a string into the SharedPreferences. This string will be the values selected
* from the {@link #setEntryValues(CharSequence[])} array.
*
*/
public class MultiSelectListPreference extends ListPreference {
@Nonnull
private static final String DEFAULT_SEPARATOR = ";";
@Nonnull
private final org.solovyev.common.text.Mapper> mapper;
private boolean[] checkedIndices;
/*
**********************************************************************
*
* CONSTRUCTORS
*
**********************************************************************
*/
public MultiSelectListPreference(Context context) {
this(context, null);
}
public MultiSelectListPreference(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
String separator = DEFAULT_SEPARATOR;
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiSelectListPreference);
for (int i = 0; i < a.getIndexCount(); i++) {
int attr = a.getIndex(i);
final String attrValue = a.getString(attr);
if (!Strings.isEmpty(attrValue)) {
switch (attr) {
case R.styleable.MultiSelectListPreference_separator:
separator = attrValue;
break;
}
}
}
this.mapper = new Mapper(separator);
this.checkedIndices = new boolean[getEntries().length];
}
@Override
public void setEntries(@Nonnull CharSequence[] entries) {
super.setEntries(entries);
checkedIndices = new boolean[entries.length];
}
@Override
protected void onPrepareDialogBuilder(@Nonnull Builder builder) {
final CharSequence[] entries = getEntries();
final CharSequence[] entryValues = getEntryValues();
if (entries == null || entryValues == null || entries.length != entryValues.length) {
throw new IllegalStateException("ListPreference requires an entries array and an entryValues array which are both the same length");
}
restoreCheckedEntries();
builder.setMultiChoiceItems(entries, checkedIndices,
new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int which, boolean value) {
checkedIndices[which] = value;
}
});
}
private void restoreCheckedEntries() {
final CharSequence[] entryValues = getEntryValues();
final List values = mapper.parseValue(getValue());
if (values != null) {
for (String value : values) {
for (int i = 0; i < entryValues.length; i++) {
final CharSequence entry = entryValues[i];
if (entry.equals(value)) {
checkedIndices[i] = true;
break;
}
}
}
}
}
@Override
protected void onDialogClosed(boolean positiveResult) {
final CharSequence[] entryValues = getEntryValues();
if (positiveResult && entryValues != null) {
final List checkedValues = new ArrayList();
for (int i = 0; i < entryValues.length; i++) {
if (checkedIndices[i]) {
checkedValues.add(entryValues[i].toString());
}
}
final String value = mapper.formatValue(checkedValues);
if (callChangeListener(value)) {
setValue(value);
}
}
}
public static class Mapper implements org.solovyev.common.text.Mapper> {
@Nonnull
private final String separator;
public Mapper(@Nonnull String separator) {
this.separator = separator;
}
@Override
public String formatValue(@Nullable List value) throws IllegalArgumentException {
return StringCollections.formatValue(value, separator, StringMapper.getInstance());
}
@Override
public List parseValue(@Nullable String value) throws IllegalArgumentException {
return StringCollections.split(value, separator, StringMapper.getInstance());
}
}
@Nonnull
public static org.solovyev.common.text.Mapper> newListMapper(@Nonnull org.solovyev.common.text.Mapper nestedMapper) {
return new ListMapper(DEFAULT_SEPARATOR, nestedMapper);
}
@Nonnull
public static org.solovyev.common.text.Mapper> newListMapper(@Nonnull org.solovyev.common.text.Mapper nestedMapper,
@Nonnull String separator) {
return new ListMapper(separator, nestedMapper);
}
private static class ListMapper implements org.solovyev.common.text.Mapper> {
@Nonnull
private final String separator;
@Nonnull
private final org.solovyev.common.text.Mapper nestedMapper;
public ListMapper(@Nonnull String separator, @Nonnull org.solovyev.common.text.Mapper nestedMapper) {
this.separator = separator;
this.nestedMapper = nestedMapper;
}
@Override
public String formatValue(@Nullable List value) throws IllegalArgumentException {
return StringCollections.formatValue(value, separator, nestedMapper);
}
@Override
public List parseValue(@Nullable String value) throws IllegalArgumentException {
return StringCollections.split(value, separator, nestedMapper);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy