Использование нескольких пользовательских настроек: изменения, расположение, заголовки предпочтений и общие значения предпочтений - PullRequest
0 голосов
/ 03 декабря 2018

Я создал настраиваемое представление предпочтений, которое отлично работает при использовании одного его экземпляра на моем экране предпочтений, однако при вставке нескольких экземпляров все становится беспорядочным.Некоторые экземпляры берут название других, когда нажимаем, скажем, view1, затем view2 фокусируется вместо этого и т. Д. Я думаю, что у меня проблема в моей функции OnCreateView или в моем атрибуте файла макета android:id.

Пожалуйста, признайте разницу между названиями предпочтений в моем pref_plates.xml (экране настроек) относительно их заголовков на снимке экрана, чтобы лучше понять мою проблему.

limited_editextpreference_view.xml (файл макета):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/widget_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/lep_sub_rl"
        android:layout_width="wrap_content"
        android:layout_height="60dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="26dp"
        android:minHeight="40dp">

        <TextView
            android:id="@+id/txt_lep_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_above="@+id/txt_lep_summary"
            android:layout_toLeftOf="@id/txt_lep_edit"
            android:text="General Ammount"
            android:ellipsize="end"
            android:gravity="bottom"
            android:textColor="#302f2f"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/txt_lep_summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_centerVertical="true"
            android:ellipsize="end"
            android:layout_toLeftOf="@id/txt_lep_edit"
            android:text="General Ammount Summary"
            android:maxLines="1"
            android:layout_alignBottom="@+id/txt_lep_edit"
            android:textSize="12sp" />

        <EditText
            android:id="@+id/txt_lep_edit"
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:layout_toLeftOf="@id/txt_lep_unit"
            android:background="@null"
            android:textColor="@color/colorAccent"
            android:layout_centerInParent="true"
            android:textAlignment="textEnd" />

        <TextView
            android:id="@+id/txt_lep_unit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:maxLength="3"
            android:text="%"
            android:paddingBottom="2dp"
            android:textColor="@color/colorAccent"
            android:textAlignment="textEnd"
            android:textSize="22sp" />

    </RelativeLayout>


</LinearLayout >

limited_edittextpreference_attrib.xml (файл пользовательских атрибутов):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="LimitedEditTextPreference">
        <attr name="lep_type" format="enum">
            <enum name="integerOnly" value="0"/>
            <enum name="doubleOnly" value="1"/>
        </attr>
        <attr name="lep_minValue" format="float"/>
        <attr name="lep_maxValue" format="float"/>
        <attr name="lep_unit" format="string"/>
    </declare-styleable>
</resources>

pref_plates.xml (экран настроек):

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

    <PreferenceCategory android:title="Contour Filtering">

        <SwitchPreference
            android:id="@+id/id_enableContourFiltering"
            android:defaultValue="true"
            android:key="enableContourFiltering"
            android:title="@string/contour_filtering" />

        <ListPreference
            android:id="@+id/id_maxPlateNumber"
            android:defaultValue="2"
            android:dependency="enableContourFiltering"
            android:entries="@array/maxPlateNumber_array"
            android:entryValues="@array/maxPlateNumber_array_values"
            android:key="maxPlateNumber"
            android:negativeButtonText="@null"
            android:positiveButtonText="@null"
            android:title="@string/maxPlateNumber" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_rRecMinArea"
            android:defaultValue="1000"
            android:dependency="enableContourFiltering"
            android:key="rRecMinArea"
            android:title="Rotated Rectangle Min Area"
            custom:lep_maxValue="1000000"
            custom:lep_minValue="1"
            custom:lep_type="integerOnly" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_rRecMaxArea"
            android:defaultValue="8799"
            android:dependency="enableContourFiltering"
            android:key="rRecMaxArea"
            android:title="Rotated Rectangle Max Area"
            custom:lep_maxValue="1000000"
            custom:lep_minValue="1"
            custom:lep_type="integerOnly" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_rRectMinRatio"
            android:defaultValue="0.19"
            android:dependency="enableContourFiltering"
            android:key="rRectMinRatio"
            android:title="Rotated Rectangle Min Ratio"
            custom:lep_maxValue="1"
            custom:lep_minValue="0.1"
            custom:lep_type="doubleOnly" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_rRectMaxRatio"
            android:defaultValue="0.83"
            android:dependency="enableContourFiltering"
            android:key="rRectMaxRatio"
            android:title="Rotated Rectangle Max Ratio"
            custom:lep_maxValue="1"
            custom:lep_minValue="0.1"
            custom:lep_type="doubleOnly" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_bBoxMinRatio"
            android:defaultValue="0.17"
            android:dependency="enableContourFiltering"
            android:key="bBoxMinRatio"
            android:title="Bounding Box Min Ratio"
            custom:lep_maxValue="1"
            custom:lep_minValue="0.1"
            custom:lep_type="doubleOnly" />


        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_bBoxMaxRatio"
            android:defaultValue="0.86"
            android:dependency="enableContourFiltering"
            android:key="bBoxMaxRatio"
            android:title="Bounding Box Max Ratio"
            custom:lep_maxValue="1"
            custom:lep_minValue="0.1"
            custom:lep_type="doubleOnly" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_extent"
            android:defaultValue="0.6"
            android:dependency="enableContourFiltering"
            android:key="extent"
            android:title="Extent"
            custom:lep_maxValue="1"
            custom:lep_minValue="0.1"
            custom:lep_type="doubleOnly" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_zrPlate"
            android:defaultValue="0.4"
            android:dependency="enableContourFiltering"
            android:key="zrPlate"
            android:title="Zr Plate"
            custom:lep_maxValue="1"
            custom:lep_minValue="0.1"
            custom:lep_type="doubleOnly" />

    </PreferenceCategory>

    <PreferenceCategory android:title="Plate Aspects">

        <SwitchPreference
            android:id="@+id/id_isAllNewPlate"
            android:defaultValue="true"
            android:disableDependentsState="true"
            android:key="isAllNewPlate"
            android:summary="@string/isAllNewPlateSummary"
            android:title="@string/isAllNewPlate" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_hightWidePlate"
            android:defaultValue="50"
            android:dependency="isAllNewPlate"
            android:key="hightWidePlate"
            android:title="Wide Plate Height"
            custom:lep_maxValue="10000"
            custom:lep_minValue="1"
            custom:lep_type="integerOnly" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_widthWidePlate"
            android:defaultValue="200"
            android:dependency="isAllNewPlate"
            android:key="widthWidePlate"
            android:title="Wide Plate Width"
            custom:lep_maxValue="10000"
            custom:lep_minValue="1"
            custom:lep_type="integerOnly" />

        <bi.anpr.layouts.LimitedEditTextPreference
            android:id="@+id/id_widthSmallPlate"
            android:defaultValue="100"
            android:dependency="isAllNewPlate"
            android:key="widthSmallPlate"
            android:title="Small Plate Width"
            custom:lep_maxValue="10000"
            custom:lep_minValue="1"
            custom:lep_type="integerOnly" />

    </PreferenceCategory>


</PreferenceScreen>

LimitedEditTextPreference.java:

package bi.anpr.layouts;

import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.sxx.vlctest.R;

public class LimitedEditTextPreference extends Preference implements InputFilter {

    private enum InputType {
        integerOnly, decimalOnly;
    }

    private int lastSavedIntValue = -1;
    private float min = 0, max = 100, dv = min, lastSavedDoubleValue = -1;
    private String unit = "";
    private InputType inputType = InputType.integerOnly;
    private EditText editText;
    private TextView txt_title, txt_summary, txt_unit;
    private Context context_;


    public LimitedEditTextPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        context_ = context;

        readAttributes(context, attrs, 0, 0);
    }

    public LimitedEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        context_ = context;

        readAttributes(context, attrs, defStyleAttr, defStyleRes);
    }

    public void readAttributes(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        TypedArray attr = null;

        if (defStyleAttr == -1)
            attr = context.obtainStyledAttributes(R.styleable.LimitedEditTextPreference);
        else
            attr = context.obtainStyledAttributes(attrs, R.styleable.LimitedEditTextPreference, defStyleAttr, defStyleRes);

        int type = attr.getInt(R.styleable.LimitedEditTextPreference_lep_type, 0);

        if (type == 1)
            inputType = InputType.decimalOnly;

        min = attr.getFloat(R.styleable.LimitedEditTextPreference_lep_minValue, 0);
        max = attr.getFloat(R.styleable.LimitedEditTextPreference_lep_maxValue, 100);
        unit = attr.getString(R.styleable.LimitedEditTextPreference_lep_unit);

        TypedArray defaltValAttr = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.defaultValue});
        dv = defaltValAttr.getFloat(0, min);

        attr.recycle();
        defaltValAttr.recycle();
    }


    @Override
    protected synchronized View onCreateView(ViewGroup parent) {
        super.onCreateView(parent);

        SharedPreferences sharedPref = context_.getSharedPreferences(getKey(), Context.MODE_PRIVATE);

        View v = initViews(parent);

        txt_title.setText(getTitle());
        txt_unit.setText(unit);

        if (getSummary() != null && getSummary().toString().trim().length() > 1)
            txt_summary.setText(getSummary());
        else {
            txt_summary.setText("");
            txt_summary.setTextSize(0);
        }

        if (inputType == InputType.integerOnly) {
            lastSavedIntValue = sharedPref.getInt(getKey(), (int) dv);
            editText.setText(String.valueOf(lastSavedIntValue));
        } else if (inputType == InputType.decimalOnly) {
            lastSavedDoubleValue = sharedPref.getFloat(getKey(), dv);
            editText.setText(String.valueOf(lastSavedDoubleValue));
        }
        editText.setFilters(new InputFilter[]{this});
        editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                String val = editText.getText().toString();
                if (!TextUtils.isEmpty(val)) {
                    if (inputType == InputType.integerOnly) {
                        if (Integer.valueOf(val) < min) {
                            Toast.makeText(context_, getTitle() + ": Accepted input Range = [" + min + ", " + max + "]", Toast.LENGTH_SHORT).show();
                            editText.setText(String.valueOf(lastSavedIntValue));
                            editText.clearFocus();
                            return;
                        } else
                            savePref(Integer.valueOf(val));
                    } else if (inputType == InputType.decimalOnly)
                        if (Float.valueOf(val) < min) {
                            Toast.makeText(context_, getTitle() + ": Accepted input Range = [" + min + ", " + max + "]", Toast.LENGTH_SHORT).show();
                            editText.setText(String.valueOf(lastSavedDoubleValue));
                            editText.clearFocus();
                            return;
                        } else
                            savePref(Float.valueOf(val));

                }
            }
        });

        return v;
    }

    @Override
    public void notifyDependencyChange(boolean disableDependents) {
        super.notifyDependencyChange(disableDependents);
        notifyChanged();

    }

    private View initViews(ViewGroup parent) {
        LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View v = li.inflate(R.layout.limited_edittextpreference_view, parent, false);

        if (editText != null)
            return v;

        editText = v.findViewById(R.id.txt_lep_edit);
        txt_title = v.findViewById(R.id.txt_lep_title);
        txt_summary = v.findViewById(R.id.txt_lep_summary);
        txt_unit = v.findViewById(R.id.txt_lep_unit);

        return v;
    }


    @Override
    protected void onBindView(View view) {
        super.onBindView(view);
        view.setClickable(true);
        view.setFocusable(false);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                editText.requestFocus();
                InputMethodManager imm = (InputMethodManager) context_.getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
            }
        });
    }

    public void savePref(Number number) {
        SharedPreferences sharedPref = context_.getSharedPreferences(getKey(), Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPref.edit();
        if (inputType == InputType.integerOnly) {
            editor.putInt(getKey(), number.intValue());
            lastSavedIntValue = number.intValue();
        } else if (inputType == InputType.decimalOnly) {
            editor.putFloat(getKey(), number.floatValue());
            lastSavedDoubleValue = number.floatValue();
        }

        editor.commit();
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
        try {
            String replacement = source.subSequence(start, end).toString();
            String newVal = dest.toString().substring(0, dstart) + replacement + dest.toString().substring(dend, dest.toString().length());

            if (newVal.equalsIgnoreCase("-")) return null;

            if (inputType == InputType.integerOnly) {
                int input = Integer.parseInt(newVal);
                if (input <= max)
                    return null;
            } else if (inputType == InputType.decimalOnly) {
                double input = Float.parseFloat(newVal);
                if (input <= max)
                    return null;
            }

        } catch (NumberFormatException nfe) {
        }

        return "";
    }

}

Снимок экрана настроек:

Preference Screen Screenshot

1 Ответ

0 голосов
/ 03 декабря 2018

Я решил проблему, переместив внутренние представления findViewById s из onCreateView в onBindView следующим образом:

private enum InputType {
    integerOnly, decimalOnly;
}

private int lastSavedIntValue = -1;
private float min = 0, max = 100, dv = min, lastSavedDoubleValue = -1;
private String unit = "";
private InputType inputType = InputType.integerOnly;
private EditText editText;
private TextView txt_title, txt_summary, txt_unit;
private Context context_;


public LimitedEditTextPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    context_ = context;

    readAttributes(context, attrs, -1, -1);
}

public LimitedEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    context_ = context;

    readAttributes(context, attrs, defStyleAttr, defStyleRes);
}

public void readAttributes(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    TypedArray attr = null;

    if (defStyleAttr == -1)
        attr = context.obtainStyledAttributes(attrs, R.styleable.LimitedEditTextPreference);
    else
        attr = context.obtainStyledAttributes(attrs, R.styleable.LimitedEditTextPreference, defStyleAttr, defStyleRes);

    int type = attr.getInt(R.styleable.LimitedEditTextPreference_lep_type,0);

    if (type==1)
        inputType = InputType.decimalOnly;

    min = attr.getFloat(R.styleable.LimitedEditTextPreference_lep_minValue, 0);
    max = attr.getFloat(R.styleable.LimitedEditTextPreference_lep_maxValue, 100);
    unit = attr.getString(R.styleable.LimitedEditTextPreference_lep_unit);

    TypedArray defaltValAttr = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.defaultValue});
    dv = defaltValAttr.getFloat(0, min);

    attr.recycle();
    defaltValAttr.recycle();
}


@Override
protected synchronized View onCreateView(ViewGroup parent) {
    super.onCreateView(parent);

    LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = li.inflate(R.layout.limited_edittextpreference_view, parent, false);

    return v;
}

@Override
public void notifyDependencyChange(boolean disableDependents) {
    super.notifyDependencyChange(disableDependents);
    notifyChanged();

}


@Override
protected void onBindView(View view) {
    super.onBindView(view);

    SharedPreferences sharedPref = context_.getSharedPreferences("Configs", Context.MODE_PRIVATE);


    editText = (EditText) view.findViewById(R.id.txt_lep_edit);
    txt_title = (TextView) view.findViewById(R.id.txt_lep_title);
    txt_summary = (TextView) view.findViewById(R.id.txt_lep_summary);
    txt_unit = (TextView) view.findViewById(R.id.txt_lep_unit);

    txt_title.setText(getTitle());
    txt_unit.setText(unit);

    if (getSummary() != null && getSummary().toString().trim().length() > 1)
        txt_summary.setText(getSummary());
    else {
        txt_summary.setText("");
        txt_summary.setTextSize(0);
    }

    if (inputType == InputType.integerOnly) {
        lastSavedIntValue = sharedPref.getInt(getKey(), (int) dv);
        editText.setText(String.valueOf(lastSavedIntValue));
    } else if (inputType == InputType.decimalOnly) {
        lastSavedDoubleValue = sharedPref.getFloat(getKey(), dv);
        editText.setText(String.valueOf(lastSavedDoubleValue));
    }

    editText.setFilters(new InputFilter[]{this});
    editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            String val = editText.getText().toString();
            if (!TextUtils.isEmpty(val)) {
                if (inputType == InputType.integerOnly) {
                    if (Integer.valueOf(val) < min) {
                        Toast.makeText(context_, getTitle() + ": Accepted input Range = [" + min + ", " + max + "]", Toast.LENGTH_SHORT).show();
                        editText.setText(String.valueOf(lastSavedIntValue));
                        editText.clearFocus();
                        return;
                    } else
                        savePref(Integer.valueOf(val));
                } else if (inputType == InputType.decimalOnly)
                    if (Float.valueOf(val) < min) {
                        Toast.makeText(context_, getTitle() + ": Accepted input Range = [" + min + ", " + max + "]", Toast.LENGTH_SHORT).show();
                        editText.setText(String.valueOf(lastSavedDoubleValue));
                        editText.clearFocus();
                        return;
                    } else
                        savePref(Float.valueOf(val));

            }
        }
    });


    view.setClickable(true);
    view.setFocusable(false);
    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            editText.requestFocus();
            InputMethodManager imm = (InputMethodManager) context_.getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
        }
    });
}

public void savePref(Number number) {
    SharedPreferences sharedPref = context_.getSharedPreferences("Configs", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPref.edit();
    if (inputType == InputType.integerOnly) {
        editor.putInt(getKey(), number.intValue());
        lastSavedIntValue = number.intValue();
    } else if (inputType == InputType.decimalOnly) {
        editor.putFloat(getKey(), number.floatValue());
        lastSavedDoubleValue = number.floatValue();
    }

    editor.commit();
}

@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
    try {
        String replacement = source.subSequence(start, end).toString();
        String newVal = dest.toString().substring(0, dstart) + replacement + dest.toString().substring(dend, dest.toString().length());

        if (newVal.equalsIgnoreCase("-")) return null;

        if (inputType == InputType.integerOnly) {
            int input = Integer.parseInt(newVal);
            if (input <= max)
                return null;
        } else if (inputType == InputType.decimalOnly) {
            double input = Float.parseFloat(newVal);
            if (input <= max)
                return null;
        }

    } catch (NumberFormatException nfe) {
    }

    return "";
}
...