Issue 155: allow custom product search, and, other small tweaks I think nobody will...
[zxing.git] / android / src / com / google / zxing / client / android / ViewfinderView.java
1 /*
2  * Copyright (C) 2008 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.client.android;
18
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.graphics.Bitmap;
22 import android.graphics.Canvas;
23 import android.graphics.Paint;
24 import android.graphics.Rect;
25 import android.util.AttributeSet;
26 import android.view.View;
27
28 /**
29  * This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial
30  * transparency outside it, as well as the laser scanner animation and result points.
31  */
32 public final class ViewfinderView extends View {
33
34   private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
35   private static final long ANIMATION_DELAY = 100L;
36
37   private final Paint mPaint;
38   private final Rect mBox;
39   private Bitmap mResultBitmap;
40   private final int mMaskColor;
41   private final int mResultColor;
42   private final int mFrameColor;
43   private final int mLaserColor;
44   private int mScannerAlpha;
45
46   // This constructor is used when the class is built from an XML resource.
47   public ViewfinderView(Context context, AttributeSet attrs) {
48     super(context, attrs);
49
50     // Initialize these once for performance rather than calling them every time in onDraw().
51     mPaint = new Paint();
52     mBox = new Rect();
53     Resources resources = getResources();
54     mMaskColor = resources.getColor(R.color.viewfinder_mask);
55     mResultColor = resources.getColor(R.color.result_view);
56     mFrameColor = resources.getColor(R.color.viewfinder_frame);
57     mLaserColor = resources.getColor(R.color.viewfinder_laser);
58     mScannerAlpha = 0;
59   }
60
61   @Override
62   public void onDraw(Canvas canvas) {
63     Rect frame = CameraManager.get().getFramingRect();
64     int width = canvas.getWidth();
65     int height = canvas.getHeight();
66
67     // Draw the exterior (i.e. outside the framing rect) darkened
68     mPaint.setColor(mResultBitmap != null ? mResultColor : mMaskColor);
69     mBox.set(0, 0, width, frame.top);
70     canvas.drawRect(mBox, mPaint);
71     mBox.set(0, frame.top, frame.left, frame.bottom + 1);
72     canvas.drawRect(mBox, mPaint);
73     mBox.set(frame.right + 1, frame.top, width, frame.bottom + 1);
74     canvas.drawRect(mBox, mPaint);
75     mBox.set(0, frame.bottom + 1, width, height);
76     canvas.drawRect(mBox, mPaint);
77
78     if (mResultBitmap != null) {
79       // Draw the opaque result bitmap over the scanning rectangle
80       mPaint.setAlpha(255);
81       canvas.drawBitmap(mResultBitmap, frame.left, frame.top, mPaint);
82     } else {
83       // Draw a two pixel solid black border inside the framing rect
84       mPaint.setColor(mFrameColor);
85       mBox.set(frame.left, frame.top, frame.right + 1, frame.top + 2);
86       canvas.drawRect(mBox, mPaint);
87       mBox.set(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1);
88       canvas.drawRect(mBox, mPaint);
89       mBox.set(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1);
90       canvas.drawRect(mBox, mPaint);
91       mBox.set(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1);
92       canvas.drawRect(mBox, mPaint);
93
94       // Draw a red "laser scanner" line through the middle to show decoding is active
95       mPaint.setColor(mLaserColor);
96       mPaint.setAlpha(SCANNER_ALPHA[mScannerAlpha]);
97       mScannerAlpha = (mScannerAlpha + 1) % SCANNER_ALPHA.length;
98       int middle = frame.height() / 2 + frame.top;
99       mBox.set(frame.left + 2, middle - 1, frame.right - 1, middle + 2);
100       canvas.drawRect(mBox, mPaint);
101
102       // Request another update at the animation interval, but only repaint the laser line,
103       // not the entire viewfinder mask.
104       postInvalidateDelayed(ANIMATION_DELAY, mBox.left, mBox.top, mBox.right, mBox.bottom);
105     }
106   }
107
108   public void drawViewfinder() {
109     mResultBitmap = null;
110     invalidate();
111   }
112
113   /**
114    * Draw a bitmap with the result points highlighted instead of the live scanning display.
115    *
116    * @param barcode An image of the decoded barcode.
117    */
118   public void drawResultBitmap(Bitmap barcode) {
119     mResultBitmap = barcode;
120     invalidate();
121   }
122
123 }