8

假设我们有通过在其中绘制一些矩形ListView来扩展onDraw()方法的自定义。

class Listpicker extends ListView {
//..Some other methods here..//
    @Override
    protected void onDraw(android.graphics.Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(glassPickerBitmap, null, glassRect, semiTransparrentPaint);
    }
}

绘制的位图代表某种玻璃,它是矩形,宽度等于列表视图的宽度和一些高度。我想要的是当列表项滚动到此矩形中时,用于绘制文本的颜色(并非所有具有背景等的项)将更改为另一种颜色。因此,例如,当列表项适合以便只有一半高度的文本适合 时glassPickerBitmap,列表项的外部部分应保持其序号颜色,而内部部分glassPickerBitmap应更改其文本颜色。列表项是没有任何背景的简单 TextView。

这怎么可能实现?也许任何ColorFilters 分配给Paint? 但是哪里?滚动时甚至不调用onDraw()方法...可以在自定义视图中完成,例如,那将是's 项目?或者可能是一些颜色/着色器/不知道这里还可以使用什么叠加层,但是在哪里ListviewListViewListView

编辑(添加图像示例):

这是来自现实应用程序的一些作物的示例。有 2ListView秒:一个在左侧,另一个在右侧。玻璃是灰色的矩形。现在,左侧列表已选择“美国美元”货币。我ListView以这种方式向右滚动,该选择介于USDAfghan Afghani之间。现在,我想要的是左侧的美元货币ListView将被绘制为红色(现在确切的颜色无关紧要,我稍后将其更改为有意义的东西)并且同时,“美国美元”的底部”和右侧 ListView 中“阿富汗阿富汗尼”的顶部也将用相同的红色绘制。

此颜色更改应以动态方式完成 - 仅应在列表滚动期间更改位于玻璃矩形下方的文本部分的颜色。

*好的,这里的欧元和美元是用非标准青色绘制的特殊货币。问题至少是关于白色的文本。但是,如果也可以更改青色,那就太好了。

列表示例

4

2 回答 2

3

正如您在他们的实现中所说的那样,他们使用并更新了他们的固定位置,ListAdapter然后他们相应地更新View匹配的,这对我来说是最简单和最简单的方法,但是你没有得到半彩色文本,我认为你仍然想要:)


http://i.imgur.com/jHvuBcL.png

所以这可能是我给出的最糟糕的答案之一,对此感到抱歉,我可能会重新审视这个问题,或者希望有人可以为您指出更好的解决方案

您可以在以下位置看到一个模糊的演示:

http://telly.com/Y98DS5

肮脏的方式:

  • 创建一个Paint适当ColorMatrixColorFilter的 ,为了回答这个问题,我只是去饱和,你必须找出你的 5x4 矩阵ColorMatrix才能得到你想要的青色。Rect在下面绘制时,您还需要一些s 来定义源和目标。
  • 创建一个屏幕外BitmapCanvas您将使用它来绘制您的列表,这已完成,因此我们有适当的视图布局值,在这里您可以onSizeChanged开始注意到肮脏,因为您必须分配Bitmap尽可能大的.ListViewOutOfMemoryException
  • 覆盖draw以使用您的屏幕外Canvas并让其ListView绘制,然后您可以将其绘制到将像往常一样绘制您的列表Bitmap的给定,然后仅绘制将使用我们之前定义的不同方式绘制的部分,您将获得过度绘制对于那些像素。CanvasBitmapPaint
  • 最后画出你的预制玻璃Bitmap,我会推荐一个 n-patch(9-patch),这样它可以缩放并且在屏幕和密度上看起来很清晰,然后你会为这些像素获得更多的过度绘制。

整个蛋糕长这样:

public class OverlayView extends ListView {
  private RectF mRect;
  private Rect mSrcRect;
  private Paint mPaint;

  private Canvas mCanvas;
  private Bitmap mBitmap;
  private float mY;
  private float mItemHeight;

  public OverlayView(Context context) {
    super(context);

    initOverlay();
  }

  public OverlayView(Context context, AttributeSet attrs) {
    super(context, attrs);

    initOverlay();
  }

  public OverlayView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    initOverlay();
  }

  private void initOverlay() {
    // DO NOT DO THIS use attrs
    final Resources res = getResources();
    mY = res.getDimension(R.dimen.overlay_y);
    mItemHeight = res.getDimension(R.dimen.item_height);
    //
    mRect = new RectF();
    mSrcRect = new Rect();
    mPaint = new Paint();

    ColorMatrix colorMatrix = new ColorMatrix();
    colorMatrix.setSaturation(0);
    mPaint.setColorFilter( new ColorMatrixColorFilter(colorMatrix) );
  }

  @Override
  public void draw(Canvas canvas) {
    super.draw(mCanvas);
    canvas.drawBitmap(mBitmap, 0, 0, null);

    canvas.drawBitmap(mBitmap, mSrcRect, mRect, mPaint);
  }

  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);

    mRect.set(0, mY, w, mY + mItemHeight);
    mRect.roundOut(mSrcRect);

    mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mBitmap);
  }
}

就是说,我希望你最终得到一个更清洁的解决方案,即使你没有得到那一半的性感:)

于 2013-07-12T08:33:47.550 回答
1

首先,保留一个备用位图和画布:

class Listpicker extends ListView {
    Bitmap bitmapForOnDraw = null;
    Canvas canvasForOnDraw = null;

确保尺寸合适:

    @override
    protected void onSizeChanged (int w, int h, int oldw, int oldh) {
        if (bitmapForOnDraw != null) bitmapForOnDraw.recycle();
        bitmapForOnDraw = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        canvasForOnDraw = new Canvas(bitmapForOnDraw);
    }

当我们开始绘制列表时:

    @override
    protected void onDraw(android.graphics.Canvas realCanvas) {
        // Put the list in place
        super.onDraw(realCanvas);

        // Now get the same again
        canvasForOnDraw.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
        super.onDraw(canvasForOnDraw);
        // But now change the colour of the white text
        canvasForOnDraw.drawColor(0xffff00ff, PorterDuff.Mode.MULTIPLY);

        // Copy the different colour text into the right place
        canvas.drawBitmap(bitmapForOnDraw, glassRect, glassRect overwritePaint);

        // finally, put the box on.
        canvas.drawBitmap(glassPickerBitmap, null, glassRect, semiTransparrentPaint);
    }
于 2013-07-14T17:02:32.910 回答