How to display 2 views, with a gradient-fade effect on Android? -
i want have 2 views displayed on screen - 1 camera preview, on top, while other 1 show image or google map - , live on bottom of screen.
i want have gradient-like transition between them though - there's no rough edge between them. possible have such effect?
edit: effect i'd achieve should (top part comes camera preview, while bottom part should map...):

on ios got similar effect cameraoverlay showing map , setting layer masp gradient:
cagradientlayer *gradient = [cagradientlayer layer]; gradient.frame = self.map.bounds; gradient.colors = [nsarray arraywithobjects:(id)[[uicolor colorwithwhite: 1.0 alpha: 0.0] cgcolor], (id)[[uicolor colorwithwhite: 1.0 alpha: 1.0] cgcolor], nil]; gradient.startpoint = cgpointmake(0.5f, 0.0f); gradient.endpoint = cgpointmake(0.5f, 0.5f); self.map.layer.mask = gradient;
this possible, perhaps bit complicated. keep simple, i've put core code achieving in answer. has been noted, need 2 views this, 1 "on top of" other. "lower" 1 should surfaceview, driven maps api. "higher" 1 should show camera image faded out on it.
edit: mr_archano points out, api (now) defined such without surfaceview camera wont send out preview data. ho hum, such nature of progress, however, surmountable.
the code presents:
- the "lower" surfaceview driven directly camera preview mechanism.
- the "middle" surfaceview maps api.
- the "upper" view camera data rendered achieve desired effect.
the core code therefore gives "camera preview" on "camera preview", , upper picture has been intentionally distorted it's visible @ top, fading in middle , gone @ bottom.
may suggest best way use code implement these first 4 steps on own , see working, add 2 final steps , see working, before inserting key concepts another, doubtless larger , more complex, piece of code.
first 4 steps:
create custom view display top, camera, view. class renders bitmap on whatever underneath it. alpha value in each pixel in bitmap determine how of lower view let through.
public class cameraoverlayview extends view { private paint paint; private size incomingsize; private bitmap bitmap = null; public cameraoverlayview(context context) { super(context); init(); } public cameraoverlayview(context context, attributeset attrs) { super(context, attrs); init(); } private void init() { paint = new paint(); paint.setstyle(style.fill_and_stroke); paint.setcolor(0xffffffff); paint.settextsize((float) 20.0); } @override protected void ondraw(canvas canvas) { super.ondraw(canvas); int width = canvas.getwidth(); int height = canvas.getheight(); canvas.drawbitmap(bitmap, 0.0f, 0.0f, paint); } }put 3 views in frame them set to
fill_parentin both directions. first 1 "underneath" (the surfaceview the camera preview works). second 1 "in middle" (the surface view maps or whatever). third "on top" (the view faded camera image).<surfaceview android:id="@+id/beneathsurfaceview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <surfaceview android:id="@+id/middlesurfaceview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <com.blah.blah.blah.cameraoverlayview android:id="@+id/abovecameraview" android:layout_width="fill_parent" android:layout_height="fill_parent" />a stripped down main activity set camera, , send automatic preview image (bottom) surfaceview , preview image data processing routine. sets callback catch preview data. these 2 run in parallel.
public class cameraoverlay extends activity implements surfaceholder.callback2 { private surfaceview backsv; private cameraoverlayview camerav; private surfaceholder camerah; private camera camera=null; private camera.previewcallback cameracpcb; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.camera_overlay); // 2 views backsv = (surfaceview) findviewbyid(r.id.beneathsurfaceview); camerav = (cameraoverlayview) findviewbyid(r.id.abovecameraview); // back: putting camera on sv (replace whatever driving sv) camerah = backsv.getholder(); camerah.addcallback(this); // front: getting data camera (for front view) cameracpcb = new camera.previewcallback () { @override public void onpreviewframe(byte[] data, camera camera) { camerav.acceptcameradata(data, camera); } }; } // making camera run , stop state changes @override public void onresume() { super.onresume(); camera = camera.open(); camera.startpreview(); } @override public void onpause() { super.onpause(); camera.setpreviewcallback(null); camera.stoppreview(); camera.release(); camera=null; } private void cameraimagetoviewon() { // front camerav.setincomingsize(camera.getparameters().getpreviewsize()); camera.setpreviewcallback(cameracpcb); } private void cameraimagetoviewoff() { // front camera.setpreviewcallback(null); } // callbacks mean camera stuff ... @override public void surfacechanged(surfaceholder holder, int format, int width, int height) { // if preview can change or rotate, take care of events here. // make sure stop preview before resizing or reformatting it. if (holder == null) return; // stop preview before making changes try { cameraimagetoviewoff(); // front camera.stoppreview(); } catch (exception e){ // ignore: tried stop non-existent preview } // set preview size , make resize, rotate or reformatting changes here // start preview new settings try { camera.setpreviewdisplay(holder); //back camera.startpreview(); cameraimagetoviewon(); // front } catch (exception e){ } } @override public void surfacecreated(surfaceholder holder) { try { camera.setpreviewdisplay(holder); //back camera.startpreview(); cameraimagetoviewon(); // front } catch (ioexception e) { } } @override public void surfacedestroyed(surfaceholder holder) { } @override public void surfaceredrawneeded(surfaceholder holder) { } }some things missing:
- ensuring camera image right orientation
- ensuring camera preview image optimal size
now, add 2 functions view created in step one. first ensures view knows size of incoming image data. second receives preview image data, turns bitmap, distorting along way both visibility , demonstrate alpha fade.
public void setincomingsize(size size) { incomingsize = size; if (bitmap != null) bitmap.recycle(); bitmap = bitmap.createbitmap(size.width, size.height, bitmap.config.argb_8888); } public void acceptcameradata(byte[] data, camera camera) { int width = incomingsize.width; int height = incomingsize.height; // bitmap want fill image int numpixels = width*height; // buffer fill fill bitmap intbuffer intbuffer = intbuffer.allocate(width*height); // if you're reusing buffer, next line imperative refill start, - if not practice intbuffer.position(0); // each pixel, 1 @ time int y; int xby2, yby2; int r, g, b, alpha; float u, v, yf; (int y = 0; y < height; y++) { // set transparency based on how far down image are: if (y<200) alpha = 255; // image @ top else if (y<455) alpha = 455-y; // fade on next 255 lines else alpha = 0; // nothing after // speed's sake, should break out of loop once alpha 0 ... (int x = 0; x < width; x++) { // y value, stored in first block of data // logical "and 0xff" needed deal signed issue y = data[y*width + x] & 0xff; // u , v values, stored after y values, 1 per 2x2 block // of pixels, interleaved. prepare them floats correct range // ready calculation later. xby2 = x/2; yby2 = y/2; u = (float)(data[numpixels + 2*xby2 + yby2*width] & 0xff) - 128.0f; v = (float)(data[numpixels + 2*xby2 + 1 + yby2*width] & 0xff) - 128.0f; // yuv -> rgb conversion yf = 1.164f*((float)y) - 16.0f; r = (int)(yf + 1.596f*v); g = 2*(int)(yf - 0.813f*v - 0.391f*u); // distorted show effect b = (int)(yf + 2.018f*u); // clip rgb values 0-255 r = r < 0 ? 0 : r > 255 ? 255 : r; g = g < 0 ? 0 : g > 255 ? 255 : g; b = b < 0 ? 0 : b > 255 ? 255 : b; // put pixel in buffer intbuffer.put(color.argb(alpha, r, g, b)); } } // buffer ready read intbuffer.flip(); // push pixel information buffer onto bitmap. bitmap.copypixelsfrombuffer(intbuffer); this.invalidate(); }notes on second routine:
- it assumes incoming camera format nv21. others may available, 1 guaranteed there, if pain. see converting yuv->rgb(image processing)->yuv during onpreviewframe in android?.
- it done faster, or better, more recent versions of android , code optimisation.
that code shows basic idea. step next phase:
set camera surface view sufficiently small hide behind non-faded section of top view. ie, change
android:layout_heightto, say,60dp.set middle surfaceview receive map information.
Comments
Post a Comment