Android中针对给定视图下的视图使用的PorterDuff颜色效果

13

在Android中,是否有可能设置一个视图,以便它对其范围内可见的所有内容应用某种颜色过滤器?就像这个例子中所示:

过滤视图

只需一个简单的矩形视图,即可反转其下方可见区域的颜色。当用户滚动列表时,反转框中也会相应地反映出来。是否有一些简单的方法可以使用颜色过滤器、PorterDuff模式等实现呢?

3个回答

15

您正在尝试使用此视图层次结构解决问题:

  • 父级
    • ListView
    • InverterView

问题在于,在此位置上,InverterView 无法控制如何绘制 ListView。但是知道谁可以控制如何绘制 ListView 吗?是 ListView 的父布局。换句话说,您真正想要的是以下层次结构:

  • 父级
    • InverterLayout
      • ListView

现在 InverterLayout 负责绘制 ListView,并且可以对其应用效果。

class InverterLayout extends FrameLayout
{
    // structure to hold our color filter
    private Paint paint = new Paint();
    // the color filter itself
    private ColorFilter cf;
    // the rectangle we want to invert
    private Rect inversion_rect = new Rect(100, 100, 300, 300);

    public InverterLayout(Context context)
    {
        super(context);
        // construct the inversion color matrix
        float[] mat = new float[]
        {
            -1,  0,  0, 0,  255,
             0, -1,  0, 0,  255,
             0,  0, -1, 0,  255,
             0,  0,  0, 1,  0
        };
        cf = new ColorMatrixColorFilter(new ColorMatrix(mat));
    }

    @Override protected void dispatchDraw(Canvas c)
    {
        // create a temporary bitmap to draw the child views
        Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
        Canvas cc = new Canvas(b);
        // draw them to that temporary bitmap
        super.dispatchDraw(cc);
        // copy the temporary bitmap to screen without the inversion filter
        paint.setColorFilter(null);
        c.drawBitmap(b, 0, 0, paint);
        // copy the inverted rectangle
        paint.setColorFilter(cf);
        c.drawBitmap(b, inversion_rect, inversion_rect, paint);
    }
}

使用时,请确保您的子视图有自己的背景。如果视图是透明的,并且窗口背景透过它显示出来,那么该窗口背景将不会被反转,因为InverterLayout无法控制窗口的绘制。


1

这是我会做的事情:

视图层次结构:

  • RelativeLayout(或FrameLayout)
    • ListView
      • CustomInverterView

InverterView通过父视图(RelativeLayout)的OnTouch定位 在onTouchListener中:

if (event.getAction() == MotionEvent.ACTION_MOVE)
           // Set Coordinates for the custom View.
           // Copy the bitmapCache of the ListView (jsut the portion you need
           // and send it to the customView.
           // Apply the filters you want.
           // Invalidate!

我使用这种方法实现了一个放大镜,它的效果非常好。也许我以后可以发布更多代码,但我现在有点忙。


1

如果我能简单地评论一下,因为我不确定我在这里是否正确。所以购买者要谨慎,以下是我的建议:

我认为您可以利用View.OnDragEventListener来实现此效果。这里是文档

我认为您应该调整Android中使用的拖放触发模型(即应用程序和操作系统之间的通信方式)。如何进行调整将完全取决于您的应用程序内部强制一个视图进入另一个视图边界的机制。一旦您找到了解决方法,就可以使用ColorMatrixPorterDuffColorFilter和其他几种高级颜色技巧。

对我来说,这听起来比替代方案Xfermode容易得多。祝你好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接