简体   繁体   English

自定义视图中子视图的 ID 在 Android 中是相同的

[英]ID of the child views in a custom view are same in Android

I have a custom view ValueSelectorView which contains two buttons to increment and decrement value and an EditText to display that value.我有一个自定义视图ValueSelectorView ,其中包含两个用于增加和减少值的按钮和一个用于显示该值的 EditText。 In my activity, I am using this view three times.在我的活动中,我使用了这个视图三次。 My concern here is with the child views that their id is always the same when checked in logs.我在这里担心的是子视图在签入日志时他们的id总是相同的。 Due to this, the resultant value comes out to be incorrect.因此,结果值不正确。

I have looked over on StackOverflow and found out that some of them have faced the same issue and they are trying to solve it by manually altering the id of the child views using setId .我查看了 StackOverflow 并发现他们中的一些人遇到了同样的问题,他们正试图通过使用setId手动更改子视图的 id 来解决它。 Tried inflating the child views using a couple of different methods but the issue still persists尝试使用几种不同的方法来膨胀子视图,但问题仍然存在

This is my custom view class这是我的自定义视图类

package eu.siacs.conversations.ui.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.RequiresApi;

import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;

public class ValueSelectorView extends RelativeLayout {

    View rootView;
    EditText valueTextView;
    View minusButton;
    View plusButton;

    private int minValue = Integer.MIN_VALUE;
    private int maxValue = Integer.MAX_VALUE;

    public ValueSelectorView(Context context) {
        super(context);
        init(context, null);
    }

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

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

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public ValueSelectorView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        rootView = LayoutInflater.from(context).inflate(R.layout.value_selector, this, true);
        Log.i(Config.LOGTAG, "****view testr**** id of this view is -->" + getResources().getResourceEntryName(rootView.getId()));
        valueTextView = rootView.findViewById(R.id.valueTextView);

        minusButton = rootView.findViewById(R.id.minusButton);
        plusButton = rootView.findViewById(R.id.plusButton);

        minusButton.setOnClickListener(v -> decrementValue());

        plusButton.setOnClickListener(v -> incrementValue());

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ValueSelectorView,0,0);
        int defaultVaue = typedArray.getInt(R.styleable.ValueSelectorView_defaultValue,0);
        Log.i(Config.LOGTAG, "****view testr**** id of this TextView is 0 -->" + valueTextView.getId());
//        Log.i(Config.LOGTAG, "****view testr**** id of this Minus Button is 0 -->" + minusButton.getId());
//        Log.i(Config.LOGTAG, "****view testr**** id of this Add Button is 0 -->" + plusButton.getId());
        valueTextView.setText(String.valueOf(defaultVaue));

        typedArray.recycle();
    }

    public void setDefaultValue(int value) {
        valueTextView.setText(String.valueOf(value));
    }

    public int getMinValue() {
        return minValue;
    }

    public void setMinValue(int minValue) {
        this.minValue = minValue;
    }

    public int getMaxValue() {
        return maxValue;
    }

    public void setMaxValue(int maxValue) {
        this.maxValue = maxValue;
    }

    public int getValue() {
        return Integer.valueOf(valueTextView.getText().toString());
    }

    /*public void setValue(int newValue) {
        int value = newValue;
        if(newValue < minValue) {
            value = minValue;
        } else if (newValue > maxValue) {
            value = maxValue;
        }
        Log.i(Config.LOGTAG, "****view testr**** id of this TextView is 1 -->" + valueTextView.getId());
        valueTextView.setText(String.valueOf(value));
    }*/

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
    }

    private void incrementValue() {

        int currentVal = Integer.valueOf(valueTextView.getText().toString());
        if(currentVal < maxValue) {
            Log.i(Config.LOGTAG, "****view testr**** id of this TextView is 2-->" + valueTextView.getId());
            valueTextView.setText(String.valueOf(currentVal + 1));
        }
    }

    private void decrementValue() {
        int currentVal = Integer.valueOf(valueTextView.getText().toString());
        if(currentVal > minValue) {
            Log.i(Config.LOGTAG, "****view testr**** id of this TextView is 3-->" + valueTextView.getId());
            valueTextView.setText(String.valueOf(currentVal - 1));
        }
    }


}

This is how I use it in my activity XML.这就是我在活动 XML 中使用它的方式。

<eu.siacs.conversations.ui.widget.ValueSelectorView
                android:id="@+id/value_selector_nights"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/margin4"
                app:defaultValue="1"
                android:gravity="center_vertical"/>

<eu.siacs.conversations.ui.widget.ValueSelectorView
                    android:id="@+id/value_selector_adults"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/margin4"
                    app:defaultValue="1"
                    android:gravity="center_vertical"/>

<eu.siacs.conversations.ui.widget.ValueSelectorView
                    android:id="@+id/value_selector_children"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:defaultValue="0"
                    android:layout_marginTop="@dimen/margin4"
                    android:gravity="center_vertical"/>

Below are the logs:以下是日志:

****view testr**** id of this view is -->value_selector_nights
****view testr**** id of this TextView is 0 -->2131297384
****view testr**** id of this view is -->value_selector_adults
****view testr**** id of this TextView is 0 -->2131297384
****view testr**** id of this view is -->value_selector_children
****view testr**** id of this TextView is 0 -->2131297384

I would like to understand how it works internally and find a solution for the same.我想了解它在内部是如何工作的,并找到相同的解决方案。 Thank you for your time.感谢您的时间。

For others, who are facing the same issue.对于面临同样问题的其他人。

My updated code is:我更新的代码是:

package eu.siacs.conversations.ui.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;

public class ValueSelectorView extends RelativeLayout {

    View rootView;
    EditText valueTextView;
    View minusButton;
    View plusButton;
    private int customState;

    private int minValue = Integer.MIN_VALUE;
    private int maxValue = Integer.MAX_VALUE;

    public ValueSelectorView(Context context) {
        super(context);
        init(context, null);
    }

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

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

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public ValueSelectorView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        rootView = LayoutInflater.from(context).inflate(R.layout.value_selector, this, true);
        Log.i(Config.LOGTAG, "****view testr**** id of this view is -->" + getResources().getResourceEntryName(rootView.getId()));
        valueTextView = rootView.findViewById(R.id.valueTextView);

        minusButton = rootView.findViewById(R.id.minusButton);
        plusButton = rootView.findViewById(R.id.plusButton);

        minusButton.setOnClickListener(v -> decrementValue());

        plusButton.setOnClickListener(v -> incrementValue());

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ValueSelectorView,0,0);
        int defaultVaue = typedArray.getInt(R.styleable.ValueSelectorView_defaultValue,0);
        Log.i(Config.LOGTAG, "****view testr**** id of this TextView is 0 -->" + valueTextView.getId());
//        Log.i(Config.LOGTAG, "****view testr**** id of this Minus Button is 0 -->" + minusButton.getId());
//        Log.i(Config.LOGTAG, "****view testr**** id of this Add Button is 0 -->" + plusButton.getId());
        valueTextView.setText(String.valueOf(defaultVaue));

        typedArray.recycle();
    }

    public void setDefaultValue(int value) {
        valueTextView.setText(String.valueOf(value));
    }

    public int getMinValue() {
        return minValue;
    }

    public void setMinValue(int minValue) {
        this.minValue = minValue;
    }

    public int getMaxValue() {
        return maxValue;
    }

    public void setMaxValue(int maxValue) {
        this.maxValue = maxValue;
    }

    public int getValue() {
        return Integer.valueOf(valueTextView.getText().toString());
    }

    /*public void setValue(int newValue) {
        int value = newValue;
        if(newValue < minValue) {
            value = minValue;
        } else if (newValue > maxValue) {
            value = maxValue;
        }
        Log.i(Config.LOGTAG, "****view testr**** id of this TextView is 1 -->" + valueTextView.getId());
        valueTextView.setText(String.valueOf(value));
    }*/

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
    }

    private void incrementValue() {

        int currentVal = Integer.valueOf(valueTextView.getText().toString());
        if(currentVal < maxValue) {
            Log.i(Config.LOGTAG, "****view testr**** id of this TextView is 2-->" + valueTextView.getId());
            valueTextView.setText(String.valueOf(currentVal + 1));
        }
    }

    private void decrementValue() {
        int currentVal = Integer.valueOf(valueTextView.getText().toString());
        if(currentVal > minValue) {
            Log.i(Config.LOGTAG, "****view testr**** id of this TextView is 3-->" + valueTextView.getId());
            valueTextView.setText(String.valueOf(currentVal - 1));
        }
    }

    public void setCustomState(int customState) {
        this.customState = customState;
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        ss.value = valueTextView.getText().toString();
        return ss;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        valueTextView.setText(ss.value);
    }

    public static class SavedState extends BaseSavedState {
        String value;

        SavedState(Parcelable superState) {
            super(superState);
        }

        public SavedState(Parcel source) {
            super(source);
            value = source.readString();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeString(value);
        }

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

Child view XML in my custom view我的自定义视图中的子视图 XML

<EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="@dimen/medium_font"
        android:enabled="false"
        android:background="@null"
        android:textColor="#000000"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@id/minusButton"
        android:saveEnabled="false"
        android:id="@+id/valueTextView" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM