В составном представлении Android не принимаются onclick из xml

Я разработал собственное составное представление, в котором есть Button и ProgressBar. Я использую databinding в своем приложении. Составное представление не принимает событие onClick, как решить эту проблему?

<com.ui.custom.LoadingButton
            android:layout_width = "match_parent"
            android:layout_height = "wrap_content"
            android:background = "@color/bg_color"
            android:onClick = "@{()->viewModel.onNextClick()}"
            android:text = "@string/next"
            android:textColor = "@color/white"
            app:isLoading = "@{viewModel.isLoading}" />

Расположение кнопки загрузки:

<?xml version = "1.0" encoding = "utf-8"?>
<layout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:app = "http://schemas.android.com/apk/res-auto">

    <data>

    </data>

    <FrameLayout
        android:id = "@+id/parentFrame"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content">

        <Button
            android:id = "@+id/button"
            android:layout_width = "match_parent"
            android:layout_height = "wrap_content"
            android:background = "?android:selectableItemBackground"
            android:textSize = "@dimen/btn_text_size" />

        <com.wang.avi.AVLoadingIndicatorView
            android:id = "@+id/loading_indicator"
            android:layout_width = "@dimen/btn_loading_indicator"
            android:layout_height = "@dimen/btn_loading_indicator"
            android:layout_gravity = "center"
            android:elevation = "@dimen/cardview_default_elevation"
            app:indicatorName = "LineSpinFadeLoaderIndicator" />
    </FrameLayout>
</layout>

Или, если я использую атрибут android onClick, как я могу получить его в TypedArray? Так что я могу настроить его для просмотра программно.

   <declare-styleable name = "LoadingButton">
        <attr name = "isLoading" format = "boolean" />
        <attr name = "android:text" />
        <attr name = "android:textColor" />
        <attr name = "android:background" />
        <attr name = "android:onClick" />

    </declare-styleable>

LoadingButton java

@BindingMethods({
        @BindingMethod(type = LoadingButton.class, attribute = "onLoadingButtonClick", method = "onLoadingButtonClick"),
})
public class LoadingButton extends LinearLayout implements View.OnClickListener {

    private Context mContext;
    private int background, textColor;
    private boolean isLoading;
    private String btnText;
    private LayoutLoadingBtnBinding itemViewBinding;
    private OnLoadingButtonListener listener;

    public LoadingButton(Context context) {
        super(context);
        initializeView(context, null, 0);
    }

    public LoadingButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        initializeView(context, attrs, 0);
    }

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

    private void initializeView(Context context, AttributeSet attrs, int defStyleAttr) {
        mContext = context;
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.LoadingButton, defStyleAttr, 0);

        try {
            background = array.getColor(R.styleable.LoadingButton_android_background, Integer.MAX_VALUE);
            textColor = array.getColor(R.styleable.LoadingButton_android_textColor, Integer.MAX_VALUE);
            btnText = array.getString(R.styleable.LoadingButton_android_text);
            isLoading = array.getBoolean(R.styleable.LoadingButton_isLoading, false);
            //   Method onClick = array.getValue(R.styleable.LoadingButton_android_onClick);
        } finally {
            array.recycle();
        }

        itemViewBinding = LayoutLoadingBtnBinding.inflate(LayoutInflater.from(mContext), this, true);

    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

      //  setOnClickListener(this::onClick);
        setValues();

    }

    private void setValues() {
        try {
            if (background != Integer.MAX_VALUE)
                itemViewBinding.parentFrame.setBackgroundColor(background);

            if (background != Integer.MAX_VALUE) {
                itemViewBinding.button.setTextColor(textColor);
                itemViewBinding.loadingIndicator.setIndicatorColor(textColor);
            }
            itemViewBinding.button.setText(btnText);
            updateLoadingViews();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void updateLoadingViews() {
        itemViewBinding.button.setVisibility(isLoading ? INVISIBLE : VISIBLE);
        itemViewBinding.loadingIndicator.setVisibility(isLoading ? VISIBLE : GONE);
    }

    public void setLoading(boolean isLoading) {
        if (this.isLoading != isLoading)  // update only if loading state is changed
        {
            this.isLoading = isLoading;
            updateLoadingViews();
        }
    }

    public void setOnLoadingButtonClick(OnLoadingButtonListener listener) {
        AppLogger.d("usm_loading_btn_0", "setOnLoadingButtonClick is called: listener= " + (listener != null));
        this.listener = listener;
    }

    @Override
    public void onClick(View view) {
        AppLogger.d("usm_loading_btn_1", "onClick is called");
        if (listener != null) {
            listener.onLoadingButtonClick();
        }
    }

    public interface OnLoadingButtonListener {
        void onLoadingButtonClick();
    }

}

Вы пробовали использовать идентификатор кнопки для реализации прослушивателя onClick?

Umair 02.08.2018 08:48

Сам родитель - LinearLayout, я хочу реализовать onClick вместо его дочернего элемента или дочернего элемента без доступа к идентификаторам

Usman Rana 02.08.2018 08:53
0
2
270
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете использовать этот способ

<attr name = "android:onClick" />

Попробуйте использовать BindingMethods

@BindingMethods({
        @BindingMethod(type = LoadingButton.class, attribute = "onLoadingButtonClick", method = "onLoadingButtonClick"),
})
public class LoadingButton extends YOUR_ROOT_VIEW implements View.OnClickListener {
  // your item view class.
  private OnLoadingButtonListener listener;

  public void setOnLoadingButtonClick(OnLoadingButtonListener listener) {
     this.listener = listener;
  }

  @Override
  public void onClick(View view) {
    if (listener != null) {
        listener.onLoadingButtonClick();
    }
  }
  public interface OnLoadingButtonListener {
    void onLoadingButtonClick();
  }
}

и в вашем макете

<com.ui.custom.LoadingButton
            android:layout_width = "match_parent"
            android:layout_height = "wrap_content"
            android:background = "@color/bg_color"
            android:onLoadingButtonClick = "@{()->viewModel.onNextClick()}"
            android:text = "@string/next"
            android:textColor = "@color/white"
            app:isLoading = "@{viewModel.isLoading}" />

ОБНОВЛЕНИЕ 1

Если ваш onClick() не работает, удалите его и попробуйте использовать этот способ.

private void initializeView(Context context, AttributeSet attrs, int defStyleAttr) {
        mContext = context;
        TypedArray array =
                context.obtainStyledAttributes(attrs, R.styleable.LoadingButton, defStyleAttr, 0);

        try {
            background =
                    array.getColor(R.styleable.LoadingButton_android_background, Integer.MAX_VALUE);
            textColor =
                    array.getColor(R.styleable.LoadingButton_android_textColor, Integer.MAX_VALUE);
            btnText = array.getString(R.styleable.LoadingButton_android_text);
            isLoading = array.getBoolean(R.styleable.LoadingButton_isLoading, false);
            //   Method onClick = array.getValue(R.styleable.LoadingButton_android_onClick);
        } finally {
            array.recycle();
        }

        itemViewBinding =
                LayoutLoadingBtnBinding.inflate(LayoutInflater.from(mContext), this, true);
        itemViewBinding.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (listener != null) {
                    listener.onLoadingButtonClick();
                }
            }
        });
    }

Спасибо за хорошее решение. Но мой onClick не звонит, хотя setOnLoadingButtonClick работает нормально.

Usman Rana 02.08.2018 10:44

все равно ... onClick не звонит

Usman Rana 02.08.2018 11:27

попробуйте еще раз с itemViewBinding.button, см. мой ответ на обновление

GianhTran 02.08.2018 11:33

Он работает при нажатии кнопки, можем ли мы заставить его работать в родительском представлении?

Usman Rana 02.08.2018 11:39

Я думаю, потому что вы используете кнопку с соответствующим родительским макетом, поэтому родительский вид не может получить прослушиватель кликов

GianhTran 02.08.2018 11:41

точка, поэтому он должен работать, если мы отключим щелчок дочернего представления. И как это сделать без привязки данных?

Usman Rana 02.08.2018 11:45

да, вы можете использовать LayoutInflater.from(getContext()).inflate(R.layout.layout_lo‌​ading_btn, this, true); для надувания макета

GianhTran 02.08.2018 11:58

Я имею в виду, что такое onClick

Usman Rana 02.08.2018 15:04

Не могли бы вы проверить этот вопрос? stackoverflow.com/questions/51096414/…

Usman Rana 10.08.2018 11:14

Другие вопросы по теме