草庐IT

android - 在滑动的 RecyclerView 项目下显示自定义 View

coder 2023-11-19 原文

首先看到这个问题:Adding a colored background with text/icon under swiped row when using Android's RecyclerView

然而,尽管标题说“带有文本/图标”,但答案仅涉及使用 Canvas 对象绘制矩形。

现在我已经绘制了一个绿色矩形;但是,我想通过添加“完成”按钮来使将要发生的事情更加明显,就像下面的屏幕截图一样。

我创建了一个自定义 View :

public class ChoosePlanView extends LinearLayout{

    public ChoosePlanView(Context context) {
        super(context);
        init();
    }

    public ChoosePlanView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ChoosePlanView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init(){
        View v = inflate(getContext(), R.layout.choose_plan_view, null);
        addView(v);
    }
}

而且布局非常简单,由绿色背景和图标组成:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" 
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/choose_green">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/doneIcon"
        android:layout_gravity="center_horizontal|right"
        android:src="@mipmap/done"/>

</LinearLayout>

我尝试覆盖方法 OnChildDraw:

// ChoosePlanView choosePlanView; <- that was declared and initialized earlier, so I don't have to create a new ChoosePlanView everytime in OnChildDraw();

ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {    

/*
    onMove, onSwiped omitted
*/
  public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
       View itemView = viewHolder.itemView;

       if(dX < 0){
            choosePlanView.invalidate();
            //choosePlanView.setBackgroundResource(R.color.delete_red);
            choosePlanView.measure(itemView.getWidth(), itemView.getHeight());
            choosePlanView.layout(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom());
            c.save();
            c.translate(choosePlanView.getRight() + (int) dX, viewHolder.getAdapterPosition()*itemView.getHeight());

            choosePlanView.draw(c);
            c.restore();
       }

       super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
  }
}

它有点管用(绘制我的 ChoosePlanView),但有两个问题。

首先,它只绘制了一个小的绿色方 block ,包裹着我的“完成”图标(下面屏幕截图中 View 的红色部分来自注释行 choosePlanView.setBackgroundResource(R.color.delete_red);)。不过,在调试器中检查时, View 具有正确的宽度。

其次是放置图标的位置。我指定我希望它水平居中并始终“粘贴”到 View 的右侧。无论它如何移动,当 RecyclerView 项目被滑动时,红色背景表明它也没有放置在中心。

我尝试添加行 choosePlanView.invalidate(),因为我认为会发生这种情况,因为 View 是较早创建的,但重绘似乎没有任何改变。

最佳答案

使用 ItemTouchUiUtil接口(interface)为此提供了强大的解决方案。它允许您在 ViewHolder 中拥有前景和背景 View ,并将所有滑动处理委托(delegate)给前景 View 。这是我用于向右滑动以删除的示例。

在你的ItemTouchHelper.Callback :

public class ClipItemTouchHelper extends ItemTouchHelper.SimpleCallback {

    ...

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        if (viewHolder != null){
            final View foregroundView = ((ClipViewHolder) viewHolder).clipForeground;

            getDefaultUIUtil().onSelected(foregroundView);
        }
    }

    @Override
    public void onChildDraw(Canvas c, RecyclerView recyclerView,
                            RecyclerView.ViewHolder viewHolder, float dX, float dY,
                            int actionState, boolean isCurrentlyActive) {
        final View foregroundView = ((ClipViewHolder) viewHolder).clipForeground;

        drawBackground(viewHolder, dX, actionState);

        getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
                actionState, isCurrentlyActive);
     }

    @Override
    public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
                                RecyclerView.ViewHolder viewHolder, float dX, float dY,
                                int actionState, boolean isCurrentlyActive) {
        final View foregroundView = ((ClipViewHolder) viewHolder).clipForeground;

        drawBackground(viewHolder, dX, actionState);

        getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
                actionState, isCurrentlyActive);
    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder){
        final View backgroundView = ((ClipViewHolder) viewHolder).clipBackground;
        final View foregroundView = ((ClipViewHolder) viewHolder).clipForeground;

        // TODO: should animate out instead. how?
        backgroundView.setRight(0);

        getDefaultUIUtil().clearView(foregroundView);
    }

    private static void drawBackground(RecyclerView.ViewHolder viewHolder, float dX, int actionState) {
        final View backgroundView = ((ClipViewHolder) viewHolder).clipBackground;

        if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
            //noinspection NumericCastThatLosesPrecision
            backgroundView.setRight((int) Math.max(dX, 0));
        }
    }
}

在你的布局文件中,定义前景和背景 View :

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/clipRow"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

        <View style="@style/Divider"/>

        <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/row_selector"
        >

        <RelativeLayout
            android:id="@+id/clipBackground"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:background="@color/swipe_bg"
            tools:layout_width="match_parent">

            <ImageView
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_centerVertical="true"
                android:layout_marginLeft="12dp"
                android:layout_marginStart="12dp"
                android:focusable="false"
                android:src="@drawable/ic_delete_24dp"
                tools:ignore="ContentDescription"/>

        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/clipForeground"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingBottom="@dimen/clip_vertical_margin"
            android:paddingLeft="@dimen/clip_horizontal_margin"
            android:paddingRight="@dimen/clip_horizontal_margin"
            android:paddingTop="@dimen/clip_vertical_margin" >

            <CheckBox
                android:id="@+id/favCheckBox"
                android:layout_width="@dimen/view_image_size"
                android:layout_height="@dimen/view_image_size"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:background="@android:color/transparent"
                android:button="@drawable/ic_star_outline_24dp"
                android:clickable="true"
                android:contentDescription="@string/content_favorite"
                />

             ...

        </RelativeLayout>

    </FrameLayout>

</LinearLayout>

关于android - 在滑动的 RecyclerView 项目下显示自定义 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32204874/

有关android - 在滑动的 RecyclerView 项目下显示自定义 View的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 编辑表单不显示嵌套项 - 2

    我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  5. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  7. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  8. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  9. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  10. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

随机推荐