java - 模糊展开的 RecyclerView 项目的周围(模糊 RecyclerView 除了其中一项)

标签 java android android-layout android-recyclerview android-viewholder

我有一个包含其子项的RecyclerView:

enter image description here

如图所示,每个项目都可以展开(例如图中的项目 i)。 在我的项目中我使用 this blur library模糊事物,例如,单击FloatingActionButton将其展开为一个对话框,并且对话框的周围被模糊,如下所示:

enter image description here

我希望展开的 RecyclerView 项目的周围也将变得模糊。我试过这个:

(Item.xml:)

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

    <com.github.mmin18.widget.RealtimeBlurView
        android:id="@+id/blur_view_per_active_goal_card"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        app:realtimeBlurRadius="20dp"
        app:realtimeOverlayColor="#8000"
        android:visibility="visible"/>

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        app:cardCornerRadius="15dp"
        app:cardElevation="10dp">

        <RelativeLayout
            android:id="@+id/root_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:id="@+id/active_goal_card"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:orientation="horizontal"
                android:padding="10dp"
                android:weightSum="10">

                <com.example.performancemeasurement.customViews.CustomProgressBar.CustomProgressBar
                    android:id="@+id/active_goal_item_progress_bar"
                    android:layout_width="0dp"
                    android:layout_height="50dp"
                    android:layout_weight="9"
                    android:transitionName="progressBar"
                    android:visibility="visible"
                    app:enable_gradient="true" />

                <ImageButton
                    android:id="@+id/active_goal_item_open_close_image_button"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="?attr/selectableItemBackground"
                    android:scaleType="fitCenter"
                    android:src="@drawable/down_vector" />

            </LinearLayout>

            <RelativeLayout
                android:id="@+id/expanded_active_goal_card"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:visibility="gone">


                <TextView
                    android:id="@+id/expanded_active_goal_card_label"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp"
                    android:layout_centerHorizontal="true"
                    android:text="Goal Name"
                    android:textColor="@android:color/black"
                    android:textSize="40sp"
                    android:textStyle="bold" />


                <com.example.performancemeasurement.customViews.CustomProgressBar.CustomProgressBar
                    android:id="@+id/expanded_active_goal_card_progress_bar"
                    android:layout_width="wrap_content"
                    android:layout_height="30dp"
                    android:layout_below="@id/expanded_active_goal_card_label"
                    android:layout_alignParentStart="true"
                    android:layout_alignParentEnd="true"
                    android:layout_marginStart="20dp"
                    android:layout_marginEnd="20dp"
                    android:layout_centerHorizontal="true"
                    android:transitionName="progressBar"
                    app:enable_gradient="true" />

                <TextView
                    android:id="@+id/expanded_active_goal_card_description"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/expanded_active_goal_card_progress_bar"
                    android:layout_centerHorizontal="true"
                    android:layout_margin="10dp"
                    android:maxLines="3"
                    android:text="Goal's Description"
                    android:textColor="#6F6F6F"
                    android:textSize="20sp"
                    android:textStyle="normal" />

                <LinearLayout
                    android:id="@+id/expanded_active_goal_card_sub_goals_label_container"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/expanded_active_goal_card_description"
                    android:layout_centerHorizontal="true"
                    android:layout_margin="5dp"
                    android:gravity="center_vertical"
                    android:orientation="horizontal"
                    android:weightSum="14">

                    <View
                        android:id="@+id/expanded_active_goal_card_sub_goal_label_left"
                        android:layout_width="0dp"
                        android:layout_height="3dp"
                        android:layout_weight="4"
                        android:background="@color/light_gray" />

                    <TextView
                        android:id="@+id/expanded_active_goal_card_sub_goals_label"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_margin="5dp"
                        android:layout_weight="6"
                        android:gravity="center"
                        android:text="SubGoals"
                        android:textColor="#5A5A5A"
                        android:textSize="25sp"
                        android:textStyle="bold" />

                    <View
                        android:id="@+id/expanded_active_goal_card_sub_goal_label_right"
                        android:layout_width="0dp"
                        android:layout_height="3dp"
                        android:layout_weight="4"
                        android:background="@color/light_gray" />

                </LinearLayout>

                <RelativeLayout
                    android:id="@+id/expanded_active_goal_card_sub_goals_container"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/expanded_active_goal_card_sub_goals_label_container"
                    android:layout_centerHorizontal="true"
                    android:layout_margin="10dp"
                    android:animateLayoutChanges="true"
                    android:elevation="15dp"
                    android:gravity="center">

                    <androidx.recyclerview.widget.RecyclerView
                        android:id="@+id/expanded_active_goal_card_sub_goals_recycler_view"
                        android:layout_width="match_parent"
                        android:layout_height="100dp" />

                </RelativeLayout>

            </RelativeLayout>

        </RelativeLayout>

    </androidx.cardview.widget.CardView>


</RelativeLayout>

(将模糊 View 放在项目内容后面,然后在 RecyclerViewViewHolder 中处理模糊可见性,就像我在每次展开/收缩项目时在对话框示例中所做的那样,但即使我在不​​处理它的情况下使其可见,模糊也不会显示。我尝试按计划以编程方式处理它,但模糊仍然没有显示。

所以问题是:具体就我而言 - 问题出在哪里?为什么模糊不显示? 一般来说...我怎样才能模糊RecyclerView的展开/聚焦项目的周围(使用RealtimeBlurView库或任何其他适合此问题解决方案的库),或者换句话说,如何模糊整个Recyclerview除了其中一个项目/如何模糊特定View的背景(模糊除此View之外的所有内容。

非常感谢您的帮助! (:

最佳答案

您必须将 RealtimeBlurView 放在另一个 View 上方才能使该 View 模糊,但在您的实现中,RealtimeBlurView 位于 CardView 下方,因此您看不到 Bure 效果。您必须将其放在布局文件中的 CardView 之后。尝试以下代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.cardview.widget.CardView
        android:id="@+id/cardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        app:cardCornerRadius="15dp"
        app:cardElevation="10dp">

        <RelativeLayout
            android:id="@+id/root_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:id="@+id/active_goal_card"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:orientation="horizontal"
                android:padding="10dp"
                android:weightSum="10">

                <com.example.performancemeasurement.customViews.CustomProgressBar.CustomProgressBar
                    android:id="@+id/active_goal_item_progress_bar"
                    android:layout_width="0dp"
                    android:layout_height="50dp"
                    android:layout_weight="9"
                    android:transitionName="progressBar"
                    android:visibility="visible"
                    app:enable_gradient="true" />

                <ImageButton
                    android:id="@+id/active_goal_item_open_close_image_button"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="?attr/selectableItemBackground"
                    android:scaleType="fitCenter"
                    android:src="@drawable/down_vector" />

            </LinearLayout>

            <RelativeLayout
                android:id="@+id/expanded_active_goal_card"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="4dp"
                android:visibility="gone">


                <TextView
                    android:id="@+id/expanded_active_goal_card_label"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp"
                    android:layout_centerHorizontal="true"
                    android:text="Goal Name"
                    android:textColor="@android:color/black"
                    android:textSize="40sp"
                    android:textStyle="bold" />


                <com.example.performancemeasurement.customViews.CustomProgressBar.CustomProgressBar
                    android:id="@+id/expanded_active_goal_card_progress_bar"
                    android:layout_width="wrap_content"
                    android:layout_height="30dp"
                    android:layout_below="@id/expanded_active_goal_card_label"
                    android:layout_alignParentStart="true"
                    android:layout_alignParentEnd="true"
                    android:layout_marginStart="20dp"
                    android:layout_marginEnd="20dp"
                    android:layout_centerHorizontal="true"
                    android:transitionName="progressBar"
                    app:enable_gradient="true" />

                <TextView
                    android:id="@+id/expanded_active_goal_card_description"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/expanded_active_goal_card_progress_bar"
                    android:layout_centerHorizontal="true"
                    android:layout_margin="10dp"
                    android:maxLines="3"
                    android:text="Goal's Description"
                    android:textColor="#6F6F6F"
                    android:textSize="20sp"
                    android:textStyle="normal" />

                <LinearLayout
                    android:id="@+id/expanded_active_goal_card_sub_goals_label_container"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@id/expanded_active_goal_card_description"
                    android:layout_centerHorizontal="true"
                    android:layout_margin="5dp"
                    android:gravity="center_vertical"
                    android:orientation="horizontal"
                    android:weightSum="14">

                    <View
                        android:id="@+id/expanded_active_goal_card_sub_goal_label_left"
                        android:layout_width="0dp"
                        android:layout_height="3dp"
                        android:layout_weight="4"
                        android:background="@color/light_gray" />

                    <TextView
                        android:id="@+id/expanded_active_goal_card_sub_goals_label"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_margin="5dp"
                        android:layout_weight="6"
                        android:gravity="center"
                        android:text="SubGoals"
                        android:textColor="#5A5A5A"
                        android:textSize="25sp"
                        android:textStyle="bold" />

                    <View
                        android:id="@+id/expanded_active_goal_card_sub_goal_label_right"
                        android:layout_width="0dp"
                        android:layout_height="3dp"
                        android:layout_weight="4"
                        android:background="@color/light_gray" />

                </LinearLayout>

                <RelativeLayout
                    android:id="@+id/expanded_active_goal_card_sub_goals_container"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/expanded_active_goal_card_sub_goals_label_container"
                    android:layout_centerHorizontal="true"
                    android:layout_margin="10dp"
                    android:animateLayoutChanges="true"
                    android:elevation="15dp"
                    android:gravity="center">

                    <androidx.recyclerview.widget.RecyclerView
                        android:id="@+id/expanded_active_goal_card_sub_goals_recycler_view"
                        android:layout_width="match_parent"
                        android:layout_height="100dp" />

                </RelativeLayout>

            </RelativeLayout>

        </RelativeLayout>

    </androidx.cardview.widget.CardView>

    <com.github.mmin18.widget.RealtimeBlurView
        android:id="@+id/blur_view_per_active_goal_card"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/cardView"
        android:layout_alignBottom="@id/cardView"
        android:layout_alignLeft="@id/cardView"
        android:layout_alignRight="@id/cardView"
        app:realtimeBlurRadius="20dp"
        app:realtimeOverlayColor="#8000"
        android:visibility="visible"/>

</RelativeLayout>


更新
由于您需要模糊除扩展项目之外的其他项目,因此您应该在适配器实现中处理它。下面的代码 fragment 展示了如何实现它。

MyAdapter.kt

class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder>(), View.OnClickListener {

    val items = ArrayList<Item>()
    var expandedItemIndex = -1

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter.MyViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_row, parent, false)
        return MyViewHolder(view, this)
    }

    override fun getItemCount() = items.size

    override fun onBindViewHolder(holder: MyAdapter.MyViewHolder, position: Int) {
        items.get(position)?.apply { holder.bind(this, expandedItemIndex) }
    }

    override fun onClick(v: View?) {
        v?.let {
            if(it.id == R.id.blur) {
                expandedItemIndex = -1
                notifyDataSetChanged()
            } else if(it.id == R.id.expand_btn) {
                val holder = it.getTag() as MyViewHolder
                if (expandedItemIndex == holder.adapterPosition) {
                    expandedItemIndex = -1;
                    notifyDataSetChanged()
                } else {
                    expandedItemIndex = holder.adapterPosition
                    notifyDataSetChanged()
                }
            }
        }
    }

    class MyViewHolder(itemView: View, onClickListener: View.OnClickListener) : RecyclerView.ViewHolder(itemView) {

        val textView : TextView = itemView.findViewById(R.id.text)
        val expandButton : ImageView = itemView.findViewById(R.id.expand_btn)
        val expandArea : View = itemView.findViewById(R.id.expanded_area);
        val blur : View = itemView.findViewById(R.id.blur);

        init {
            expandButton.setOnClickListener(onClickListener)
            blur.setOnClickListener(onClickListener)
        }

        fun bind(item: Item, expandedItemIndex: Int) {
            textView.text = item.value.toString()
            expandButton.setTag(this)
            if(expandedItemIndex >= 0) {
                blur.visibility = View.VISIBLE
                if(expandedItemIndex == adapterPosition) {
                    blur.z = -1f
                    expandArea.visibility = View.VISIBLE
                    expandButton.setImageResource(android.R.drawable.arrow_up_float)
                } else {
                    blur.z = 0f
                    expandArea.visibility = View.GONE
                    expandButton.setImageResource(android.R.drawable.arrow_down_float)
                }
            } else {
                expandArea.visibility = View.GONE
                blur.visibility = View.INVISIBLE
            }
        }
    }
}

layout_row.xml

<RelativeLayout 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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <FrameLayout
        android:id="@+id/cardHolder"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            app:cardCornerRadius="15dp"
            app:cardElevation="5dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:padding="10dp">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:orientation="horizontal">

                    <TextView
                        android:id="@+id/text"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="Header Text" />

                    <ImageView
                        android:id="@+id/expand_btn"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:padding="8dp"
                        android:src="@android:drawable/arrow_down_float" />

                </LinearLayout>

                <LinearLayout
                    android:id="@+id/expanded_area"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical"
                    android:visibility="gone"
                    tools:visibility="visible">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Expanded Line 1"></TextView>

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Expanded Line 2"></TextView>

                </LinearLayout>
            </LinearLayout>
        </androidx.cardview.widget.CardView>
    </FrameLayout>

    <com.github.mmin18.widget.RealtimeBlurView
        android:id="@+id/blur"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/cardHolder"
        android:layout_alignBottom="@id/cardHolder"
        app:realtimeBlurRadius="20dp"
        app:realtimeOverlayColor="#8000" />
</RelativeLayout>

MyAdapterJava.Java(适配器的 Java 实现)

public class MyAdapterJava extends RecyclerView.Adapter<MyAdapterJava.MyViewHolder> implements View.OnClickListener{

    List<Item> items = new ArrayList<Item>();
    int expandedItemIndex = -1;

    @NonNull
    @Override
    public MyAdapterJava.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_row, parent, false);
        return new MyViewHolder(view, this);
    }

    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public void onBindViewHolder(@NonNull MyAdapterJava.MyViewHolder holder, int position) {
        holder.bind(items.get(position), expandedItemIndex);
    }

    @Override
    public void onClick(View v) {
        if(v != null) {
            if(v.getId() == R.id.blur) {
                expandedItemIndex = -1;
                notifyDataSetChanged();
            } else if(v.getId() == R.id.expand_btn) {
                MyViewHolder holder = (MyViewHolder) v.getTag();
                if (expandedItemIndex == holder.getAdapterPosition()) {
                    expandedItemIndex = -1;
                    notifyDataSetChanged();
                } else {
                    expandedItemIndex = holder.getAdapterPosition();
                    notifyDataSetChanged();
                }
            }
        }
    }

    static class MyViewHolder extends RecyclerView.ViewHolder {

        TextView textView;
        ImageView expandButton;
        View expandArea;
        View blur;

        public MyViewHolder(View itemView, View.OnClickListener onClickListener) {
            super(itemView);

            textView = itemView.findViewById(R.id.text);
            expandButton = itemView.findViewById(R.id.expand_btn);
            expandArea = itemView.findViewById(R.id.expanded_area);
            blur = itemView.findViewById(R.id.blur);

            expandButton.setOnClickListener(onClickListener);
            blur.setOnClickListener(onClickListener);
        }

        public void bind(Item item, int expandedItemIndex) {
            textView.setText(String.valueOf(item.getValue()));
            expandButton.setTag(this);
            if(expandedItemIndex >= 0) {
                blur.setVisibility(View.VISIBLE);
                if(expandedItemIndex == getAdapterPosition()) {
                    blur.setZ(-1f);
                    expandArea.setVisibility(View.VISIBLE);
                    expandButton.setImageResource(android.R.drawable.arrow_up_float);
                } else {
                    blur.setZ(0f);
                    expandArea.setVisibility(View.GONE);
                    expandButton.setImageResource(android.R.drawable.arrow_down_float);
                }
            } else {
                expandArea.setVisibility(View.GONE);
                blur.setVisibility(View.INVISIBLE);
            }
        }
    }
}

结果将是这样的: enter image description here


PS:
1.由于此代码使用 View.SetZ(float)为了处理模糊 View Z 位置,它适用于 API 21 及更高版本。为了支持较低的 API 版本,您应该在布局文件中的 FrameLayout (cardHolder) View 之前添加另一个 Blur View ,而不是使用 View.setZ(float) 方法,使正确的 Blur View 可见。
2.当某个项目展开且其他项目模糊时,RecyclerView 的滚动仍然有效,但不会影响我的答案的功能。如果需要禁用它,您应该在 Adapter 中定义一个回调,并在 override fun onClick(v: View?) 方法中调用它,以通知 Activity 或 Fragment 禁用/启用 RecyclerView 滚动。

关于java - 模糊展开的 RecyclerView 项目的周围(模糊 RecyclerView 除了其中一项),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59969187/

相关文章:

java - 安卓颜色选择器

android - 在 xml android 中无法访问自定义 View 属性

android - 向上滚动时用动画展开 Recyclerview 项目

java - Activity 之间的Android数据检索

java - 为什么不给凶手加钱,而不给受害者减钱呢?并且消息未发送

java - 在 getter/setter 中创建一个计数器?

java - Android ListView自定义行布局

java - 在 Java 中发送 HTTP POST 请求并在 PHP 中接受 POST 请求

android - 无法在虚拟盒模拟器中运行 android 项目

android - 2x3 自定义按钮网格布局不适合 TableRow