繁体   English   中英

模糊扩展的 RecyclerView 项目的周围(模糊 RecyclerView 除了其项目之一)

[英]Blur Surrounding Of Expanded RecyclerView Item (Blur RecyclerView Except Of One Of Its Items)

我有一个RecyclerView包含它的孩子:

在此处输入图片说明

正如您在图片中看到的,每个项目都可以展开(例如图片中的项目 i)。 在我的项目中,我使用这个模糊库来模糊事物,例如,单击FloatingActionButton将其展开为一个对话框,并且对话框的周围是模糊的,如下所示:

在此处输入图片说明

我希望扩展的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>

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

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

帮助将不胜感激! (:

您必须将RealtimeBlurView放在另一个视图上方以使该视图模糊,但在您的实现中, 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>


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

我的适配器文件

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

结果将是这样的: 在此处输入图片说明


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

您可以使用模糊库https://github.com/wasabeef/Blurry 这是制作模糊背景的最简单方法。

有了这个库,你只需要使用下面的片段

Blurry.with(context).radius(10).sampling(8).color(Color.argb(66, 255, 255, 0)).async().onto(rootView);

希望这将适合您的要求完美!

暂无
暂无

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

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