自定LinearLayout的子元素未显示涟漪效果。

huangapple go评论63阅读模式
英文:

Children from custom LinearLayout not displaying ripple effect

问题

我正在使用自定义的LinearLayout(扩展LinearLayout),以便可以将适配器(BaseAdapter)附加到它上面。

(感谢原作者,当然。)

/**
 * 作者:Vincent Mimoun-Prat @ MarvinLabs
 */
public class MyLinearLayout extends LinearLayout {
    private static final String TAG = "MyLinearLayout";
    private Adapter adapter;

    // 其他部分的代码...
    
    private void reloadChildViews() {
        removeAllViews();

        if (adapter == null) return;

        int count = adapter.getCount();
        for (int position = 0; position < count; ++position) {
            View v = adapter.getView(position, null, this);
            if (v != null) {
                int[] attrs = new int[]{R.attr.selectableItemBackground};

                TypedArray typedArray = getContext().obtainStyledAttributes(attrs);

                int backgroundResource = typedArray.getResourceId(0, 0);

                v.setBackgroundResource(backgroundResource);

                typedArray.recycle();

                addView(v);
            }
        }

        requestLayout();
    }
}

所以,我基本上通过addView()方法动态添加每个子视图。
正如您所看到的,我已经尝试在每个以编程方式添加的子视图上添加了涟漪效果。

添加到这个ViewGroup的子视图具有相应的属性:

<layout xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="contentProduct"
            type="com.example.flyhigh.data.pojos_entities.content.variations.ContentProduct" />
        <variable
            name="touchListener"
            type="android.view.View.OnTouchListener"/>
    </data>
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:context="com.example.flyhigh.ui.DailyJournalFragment"
        android:clickable="true"
        android:focusable="true"
        setOnTouchListener="@{touchListener}"
        android:background="?android:attr/selectableItemBackground">
        <TextView
            <!-- 其他子视图 -->
        </TextView>
    </LinearLayout>
</layout>

绑定的touchListener正在按预期工作。

LinearLayout如下:

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.flyhigh.adapters.PhaseTypePagerAdapter2">
    <com.example.flyhigh.custom_artifacts.MyLinearLayout
        android:id="@+id/myLinearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        android:orientation="vertical"
        android:background="?selectableItemBackground" <!-- 我尝试过开启和关闭这个 -->
        android:clickable="true" <!-- 我尝试过开启和关闭这个 -->
        android:focusable="true" <!-- 我尝试过开启和关闭这个 -->
        android:divider="@drawable/divider"
        android:dividerPadding="10dp"
        android:showDividers="middle"
        />
</layout>

这个LinearLayout位于ViewPager内。
这个ViewPager在没有FragmentManager的情况下工作(它的适配器是PagerAdapter)。
我怎么知道是LinearLayout遮挡了子视图而不是ViewPager遮挡了一切?因为当调整LinearLayout的属性时,更改变得可见,包括在触摸子视图之外时LinearLayout本身的涟漪效果(我为此留了一些空间以便可能发生)。

如果您想看ViewPager的代码:

<com.example.flyhigh.custom_artifacts.MyViewPager
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toTopOf="parent">
</com.example.flyhigh.custom_artifacts.MyViewPager>

我计划为每个子视图添加拖放功能,但我担心这个问题也会影响到该功能。
我百分之百确定解决方案在MyLayout类中覆盖一个方法,但是哪一个方法呢?

英文:

I'm using a custom LinearLayout (extends LinearLayout), so that and Adapter (BaseAdapter) can be attached to it.

(Thanks to the original author ofc.)

 * @author Vincent Mimoun-Prat @ MarvinLabs
 */
public class MyLinearLayout extends LinearLayout {
    private static final String TAG = &quot;MyLinearLayout&quot;;
    private Adapter adapter;

....

private void reloadChildViews() {
    removeAllViews();

    if (adapter == null) return;

    int count = adapter.getCount();
    for (int position = 0; position &lt; count; ++position) {
        View v = adapter.getView(position, null, this);
        if (v != null) {
            int[] attrs =new int[]{R.attr.selectableItemBackground};

            TypedArray typedArray =getContext().obtainStyledAttributes(attrs);

            int backgroundResource =typedArray.getResourceId(0, 0);

            v.setBackgroundResource(backgroundResource);

            typedArray.recycle();

            addView(v);
        }

    }

    requestLayout();
}

}

So I'm basically adding each child dynamically via addView() method.
As you can see I've already attempted to place a ripple effect on each child view added programatically.

The child view that is added to this ViewGroup has the according attrs:

&lt;layout xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    &gt;
    &lt;data&gt;
    &lt;variable
        name=&quot;contentProduct&quot;
        type=&quot;com.example.flyhigh.data.pojos_entities.content.variations.ContentProduct&quot; /&gt;
    &lt;variable
        name=&quot;touchListener&quot;
        type=&quot;android.view.View.OnTouchListener&quot;/&gt;
    &lt;/data&gt;
    &lt;LinearLayout
        android:orientation=&quot;horizontal&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;wrap_content&quot;
        tools:context=&quot;com.example.flyhigh.ui.DailyJournalFragment&quot;
        android:clickable=&quot;true&quot;
        android:focusable=&quot;true&quot;
        setOnTouchListener=&quot;@{touchListener}&quot;
        android:background=&quot;?android:attr/selectableItemBackground&quot;
        &gt;
        &lt;TextView

.....
        /&gt;
&lt;/LinearLayout&gt;
&lt;/layout&gt;

The touchListener binded is working accordingly.

The LinearLayout:

&lt;layout
    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    tools:context=&quot;com.example.flyhigh.adapters.PhaseTypePagerAdapter2&quot;
&gt;
&lt;com.example.flyhigh.custom_artifacts.MyLinearLayout
    android:id=&quot;@+id/myLinearLayout&quot;

    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;

    app:layout_constraintTop_toTopOf=&quot;parent&quot;

    android:orientation=&quot;vertical&quot;
    android:background=&quot;?selectableItemBackground&quot; //I&#39;ve tried with this on and off
    android:clickable=&quot;true&quot; //I&#39;ve tried with this on and off
    android:focusable=&quot;true&quot; //I&#39;ve tried with this on and off


    android:divider=&quot;@drawable/divider&quot;
    android:dividerPadding=&quot;10dp&quot;
    android:showDividers=&quot;middle&quot;

    /&gt;

&lt;/layout&gt;

This LinearLayout is inside a ViewPager.
This ViewPager is working without FragmentManager (its Adapter is a PagerAdapter).
How do I know its the LinearLayout obfuscating the children and not the ViewPager obfuscating everything? because when playing around the LinearLayout attributes, the changes become visible, this includes the actual ripple effect of the LinearLayout itself (not its children) when touched outside a children (I've given some room for this to be possible).

In case you want to see the ViewPager:

        &lt;com.example.flyhigh.custom_artifacts.MyViewPager
            android:id=&quot;@+id/main_container&quot;
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;wrap_content&quot;
            app:layout_constraintTop_toTopOf=&quot;parent&quot;
            &gt;

I'm planning to add a Drag and Drop functionality to each children but I'm afraid that this symptom will reach that functionality also.

I'm 100% sure the solution relies on overriding a Method in the MyLayout class but which one?

答案1

得分: 2

关于视图重叠顺序,我似乎对一些概念有了错误的理解。
看起来,顺序总是最后嵌套的对象位于所有其他内容之上(我怎么可能会想得不同...),也许是我被代码的嵌套写法搞混了...

无论如何...

问题不是父ViewGroup遮挡了它更内部的子元素,而是相反的情况:

总是子元素遮挡了它的父元素。

回顾我的最初问题,我以为我的外部布局(一个自定义的LinearLayout)阻止了列表项(也是一个ViewGroup)的波纹效果。

所以,解决方案,不使用似乎很流行的android:foreground=,是下面这个:

在你想要添加波纹效果的ViewGroup内部(我的列表项):

<LinearLayout
    ...
    android:clickable="true"
    android:focusable="true"
    android:background="?android:attr/selectableItemBackground"
    android:addStatesFromChildren="true" // 这是重要的部分,但如果没有其他属性就没用
    >

    // 遮挡子元素应该有相应的:
    <TextView
        ...
        android:clickable="true"
        android:focusable="true"
        ...
    />

    <TextView
        ...
        android:clickable="true"
        android:focusable="true"
        ...
    />

    <TextView
        ...
        android:clickable="true"
        android:focusable="true"
        ...
    />

    等等...等等...等等...
</LinearLayout>

希望这对你有帮助。

英文:

I appear to have had some concepts wrong about the order of how views overlap.
It seems that the order will always be that the last nested object is the one on top of everything else (how could I've thought it otherwise...), maybe I was confused by the way the code is written (in a nested way)...

Anyways...

The problem wasn't that the parent ViewGroup was obfuscating its more inner children, BUT the other way around:

It's always the children that obfuscate its parent.

To reprise my initial question, I thought my outer layout (a custom LinearLayout) was preventing the ripple effect from its list items (a ViewGroup also).

So, the solution, without using the android:foreground= that seems to be a popular one, is the next one:

This inside the ViewGroup you want highlighted with ripple effect (my list item):

&lt;LinearLayout
    ...
    android:clickable=&quot;true&quot;
    android:focusable=&quot;true&quot;
    android:background=&quot;?android:attr/selectableItemBackground&quot;
    android:addStatesFromChildren=&quot;true&quot; // this is the important one, but without the other attrs is useless
    &gt;

//obfuscating children should have the according:
    &lt;TextView
        ...
        android:clickable=&quot;true&quot;
        android:focusable=&quot;true&quot;
        ...
    /&gt;

    &lt;TextView
        ...
        android:clickable=&quot;true&quot;
        android:focusable=&quot;true&quot;
       ...
    /&gt;

    &lt;TextView
        ...
        android:clickable=&quot;true&quot;
        android:focusable=&quot;true&quot;
       ...
    /&gt;

    Etc...etc...etc...
    &lt;/LinearLayout&gt;

huangapple
  • 本文由 发表于 2020年8月9日 05:41:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63320473.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定