Search code examples
androidandroid-layoutwebviewscrollviewonclicklistener

Layout onClick event does not work if it has Webview as a child


My Issue is that I have a LinearLayout that I am inflating at runtime to a LinearLayout inside ScrollView.
This is the main_activity.xml

<ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/controlLayoutCV"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/toolLayoutCV">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="@dimen/dp5"
            android:paddingLeft="@dimen/dp7"
            android:paddingRight="@dimen/dp7"
            android:paddingTop="@dimen/dp5">

            <android.support.v7.widget.CardView
                android:id="@+id/questionQuizCV"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:cardElevation="@dimen/dp2">

                <com.emedicoz.app.CustomViews.JustifiedTextView
                    android:id="@+id/questionQuizTV"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="@dimen/dp5"
                    android:text="" />
            </android.support.v7.widget.CardView>

            <LinearLayout
                android:id="@+id/quizQuestionLL"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/questionQuizCV"
                android:layout_marginTop="@dimen/dp5"
                android:orientation="vertical"
                android:padding="@dimen/dp5" />

        </RelativeLayout>
 </ScrollView>


& this is the item_layout.xml

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mcqlayout_LL"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="@dimen/dp5"
    android:minHeight="30dp"
    android:orientation="horizontal"
    android:paddingBottom="@dimen/dp7"
    android:paddingTop="@dimen/dp7">

    <TextView
        android:id="@+id/optioniconTV"
        android:layout_width="@dimen/dp40"
        android:layout_height="@dimen/dp40"
        android:background="@drawable/circle_bg"
        android:gravity="center"
        android:padding="@dimen/dp3"
        android:text="A"
        android:textSize="@dimen/sub_heading_text_size" />

    <com.emedicoz.app.CustomViews.JustifiedTextView
        android:id="@+id/optionTextTV"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="@dimen/dp10" />
</LinearLayout>

This is the CustomTextView that I have created to show the HTML content directly. The JustifiedTextView.class is

public class JustifiedTextView extends WebView {
    private String text = "";
    private int textSize = 12;
    private int backgroundColor = Color.TRANSPARENT;

    public JustifiedTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setWebChromeClient(new WebChromeClient() {});
    }

    public void setText(String s) {
        this.text = s;
        reloadData();
    }

    @SuppressLint("NewApi")
    private void reloadData() {

        // loadData(...) has a bug showing utf-8 correctly. That's why we need to set it first.
        this.getSettings().setDefaultTextEncodingName("utf-8");

        //        this.loadData(String.format(core,textColor,textSize,text), "text/html","utf-8");
        this.loadData(text, "text/html", "utf-8");

        // set WebView's background color *after* data was loaded.
        super.setBackgroundColor(backgroundColor);

        // Hardware rendering breaks background color to work as expected.
        // Need to use software renderer in that case.
        if (android.os.Build.VERSION.SDK_INT >= 11)
            this.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
            Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }

    public void setTextSize(int textSize) {
        this.textSize = textSize;
        reloadData();
    }
}

I have tried All of the solutions mentioned below.

  1. Disable WebView touch events in Android
  2. Already tried to set the android:descendantFocusability="blocksDescendants" to ScrollView

Why the click Event of LinearLayout does not fire when making click on WebView?

This is the way I am inflating the Layout and handle the click event.

    private LinearLayout initAnswerMCViews(String text, String questions, Questions questionsModel) {
    LinearLayout view = (LinearLayout) View.inflate(activity, R.layout.mcq_quiz, null);

    answerTV = (JustifiedTextView) view.findViewById(R.id.optionTextTV);
    optionIconTV = (TextView) view.findViewById(R.id.optioniconTV);
    mcqItemLL = (LinearLayout) view.findViewById(R.id.mcqlayout_LL);

    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
    lp.setMargins(3, 3, 3, 3);
    mcqItemLL.setLayoutParams(lp);

    if (questionsModel.isAnswered()) {
        String[] answer = questionsModel.getUser_answer().split(",");
        for (int i = 0; i < answer.length; i++) {
            if (answer[i].equals(text)) {
                answerTV.setText(questions);
                optionIconTV.setText(text);
                optionIconTV.setBackgroundResource(R.drawable.circle_bg_true);
            } else {
                answerTV.setText(questions);
                optionIconTV.setText(text);
            }
        }
    } else {
        answerTV.setText(questions);
        optionIconTV.setText(text);
    }

    mcqItemLL.setTag(R.id.questions, optionIconTV.getText().toString());
    mcqItemLL.setTag(R.id.optionsAns, mcqItemLL);
    mcqItemLL.setOnClickListener(optionClickListener);
    viewArrayList.add(mcqItemLL);
    return view;
}

Why the click is not get listen when clicked on the WebView part in the Layout?

enter image description here


Solution

  • I finally found the issue.
    It is basically the issue of conflicting Touch Event of both parent Scrollview and CustomWebView.
    So, by using the new classes that itself overriding the ClickListener and TouchListener.

    package com.app.CustomViews;
    
    import android.content.Context;
    import android.os.Build;
    import android.util.AttributeSet;
    import android.view.GestureDetector;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import android.webkit.WebView;
    
    
    public class TestSeriesOptionWebView extends WebView implements GestureDetector.OnGestureListener {
        private boolean check = false;
    
        class LongClick implements OnLongClickListener {
            final /* synthetic */ TestSeriesOptionWebView testSeriesOptionWebView;
    
            LongClick(TestSeriesOptionWebView testSeriesOptionWebView) {
                this.testSeriesOptionWebView = testSeriesOptionWebView;
            }
    
            public boolean onLongClick(View view) {
                return true;
            }
        }
    
        public TestSeriesOptionWebView(Context context) {
            super(context);
            handleClick();
        }
    
        public TestSeriesOptionWebView(Context context, AttributeSet attributeSet) {
            super(context, attributeSet);
            handleClick();
        }
    
        public TestSeriesOptionWebView(Context context, AttributeSet attributeSet, int i) {
            super(context, attributeSet, i);
            handleClick();
        }
    
        private void handleClick() {
            setFocusable(false);
            /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                setLayerType(View.LAYER_TYPE_HARDWARE, null);
            } else {
                setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            }*/
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
            setVerticalScrollBarEnabled(false);
            setBackgroundColor(0);
            setHapticFeedbackEnabled(false);
            setOnLongClickListener(new LongClick(this));
        }
    
        public void setDisableWebViewTouchListener(boolean z) {
            this.check = z;
        }
    
        public boolean onTouchEvent(MotionEvent motionEvent) {
            if (this.check) {
                return false;
            }
            return super.onTouchEvent(motionEvent);
        }
    
        public boolean canScrollHorizontal(int i) {
            int computeHorizontalScrollOffset = computeHorizontalScrollOffset();
            int computeHorizontalScrollRange = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
            if (computeHorizontalScrollRange == 0) {
                return false;
            }
            if (i < 0) {
                if (computeHorizontalScrollOffset <= 0) {
                    return false;
                }
                return true;
            } else if (computeHorizontalScrollOffset >= computeHorizontalScrollRange - 1) {
                return false;
            } else {
                return true;
            }
        }
    
        @Override
        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
                    Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
            ViewGroup.LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();
        }
    
        public boolean onDown(MotionEvent motionEvent) {
            return true;
        }
    
        public void onShowPress(MotionEvent motionEvent) {
        }
    
        public boolean onSingleTapUp(MotionEvent motionEvent) {
            return false;
        }
    
        public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent2, float f, float f2) {
            return f != 0.0f;
        }
    
        public void onLongPress(MotionEvent motionEvent) {
        }
    
        public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent2, float f, float f2) {
            return true;
        }
    }  
    

    If anybody faces this type of issue, then Use this Custom Class TestSeriesOptionWebView.class.