Setting up a cover flow in Android - android

I created an iphone application, and now I am consigned to do the same application in android. I used the OpenFlow from thefaj on github https://github.com/thefaj/OpenFlow
however I have yet to be able to find something with a working coverflow on the android..
Does anyone have experience with this in android or know a good place to start ?

I used this code on my project
http://www.inter-fuser.com/2010/02/android-coverflow-widget-v2.html
You can adapt it to load the contents from some datasource, it's not a hard work.

Just came across http://code.google.com/p/android-coverflow/ which seems to be based in the inter-fuser code with some optimisations

Extend Gallery, and override this method as so:
protected boolean getChildStaticTransformation(View child, Transformation t) {
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);
final Matrix matrix = t.getMatrix();
float childCenterPos = child.getLeft() + (child.getWidth() / 2f);
float center = getWidth() / 2;
float diff = Math.abs(center - childCenterPos);
float scale = diff / getWidth();
matrix.setScale(1 - (scale), 1 - (scale));
return true;
}
Obviously you can do more interresting stuff with the matrix than just scaling, but this just as an example of how easy it can be done.

Related

360 panorama viewer with rajawali + VR howto change FieldOfView

I am trying to create a 360 image viewer using rajawali + vr (Cardboard toolkit).
When i disable the VR-Mode on the CardboardView the changes i made on Field of View property in the renderer has no effect.
in the Google Cardboard docs i found the the view will ignore it
For monocular rendering, the implementor should feel free to ignore the FieldOfView and instead create a perspective matrix with whatever field of view is desired for monocular rendering
My Question is how can i do this?
and where should i implement it, neither the renderer nor the CardboardView has a method to set an perspectiveMatrix (float[])?
updating the device param seems to always get overwritten by the gvr view
but if you decompile the FieldOfView class, you get this:
public void toPerspectiveMatrix(float near, float far, float[] perspective, int offset) {
if(offset + 16 > perspective.length) {
throw new IllegalArgumentException("Not enough space to write the result");
} else {
float l = (float)(-Math.tan(Math.toRadians((double)this.left))) * near;
float r = (float)Math.tan(Math.toRadians((double)this.right)) * near;
float b = (float)(-Math.tan(Math.toRadians((double)this.bottom))) * near;
float t = (float)Math.tan(Math.toRadians((double)this.top)) * near;
Matrix.frustumM(perspective, offset, l, r, b, t, near, far);
}
}

BitmapTransformation in the Glide library not working as expected

I'm new to the Glide library, following the Transformations guide found here: https://github.com/bumptech/glide/wiki/Transformations
I'm trying to create a custom transformation, but when I place a breakline in the Transformation class's transform method, I can see that it is never called.
Below is my code:
private static class CustomTransformation extends BitmapTransformation {
private Context aContext;
public CustomTransformation(Context context) {
super(context);
aContext = context;
}
#Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
return bitmapChanger(toTransform, 1080, (int) aContext.getResources().getDimension(R.dimen.big_image));
}
#Override
public String getId() {
return "some_id";
}
}
private static Bitmap bitmapChanger(Bitmap bitmap, int desiredWidth, int desiredHeight) {
float originalWidth = bitmap.getWidth();
float originalHeight = bitmap.getHeight();
float scaleX = desiredWidth / originalWidth;
float scaleY = desiredHeight / originalHeight;
//Use the larger of the two scales to maintain aspect ratio
float scale = Math.max(scaleX, scaleY);
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
//If the scaleY is greater, we need to center the image
if(scaleX < scaleY) {
float tx = (scale * originalWidth - desiredWidth) / 2f;
matrix.postTranslate(-tx, 0f);
}
return Bitmap.createBitmap(bitmap, 0, 0, (int) originalWidth, (int) originalHeight, matrix, true);
}
I've tried initiating Glide in two ways:
Glide.with(this).load(url).asBitmap().transform(new CustomTransformation(this)).into(imageView);
and
Glide.with(this).load(url).bitmapTransform(new CustomTransformation(this)).into(imageView);
But neither work. Any ideas? Again, I'm not looking for advice on the Matrix itself, I just don't understand why transform(...) isn't being called at all. Thanks!
You're most likely experiencing caching issues. The first time you compiled and executed your code the result of the transformation was cached so next time it doesn't have to be applied to the same source image.
Each transformation has a getId() method which is used in determining whether the transformation result has changed. Usually transformations don't change, but are either applied or not. You can change it on every build while developing, but it could be tedius.
To work around this problem you can add the following two calls to your Glide load line:
// TODO remove after transformation is done
.diskCacheStrategy(SOURCE) // override default RESULT cache and apply transform always
.skipMemoryCache(true) // do not reuse the transformed result while running
The first one can be changed to NONE, but then you would have to wait for the url to load from the internet every time, instead of just reading the image from the phone. The second one is useful if you have can navigate to and away from the transformation in question and want to debug it for example. It helps to not need a restart after every load to clear the memory cache.
Don't forget to remove these after you're done with the Transformation's development, because they affect production performance a lot and should be used after much consideration only, if at all.
Note
It looks like you're trying to resize your image to a certain size before loading, you can use .override(width, height) in combination with .centerCrop()/.fitCenter()/.dontTransform() for that.

Drag and Drop Libgdx, without a Target

Im trying to implement the Drag And Drop method/class in libgdx, but what´s different for me is that I dont have a "Target" to drop my actor. I simply want to drag it around all over the screen. I haven´t really got any further than this.
dd = new DragAndDrop();
dd.addSource(new Source(stoneImage){
#Override
public Payload dragStart(InputEvent event, float x, float y, int pointer) {
Payload payload = new Payload();
payload.setObject("some payload");
payload.setDragActor(stoneImage);
return payload;
}
});
Here I set the Image as an actor:
stageMove.addActor(stoneImage);
At the moment it won´t move when I try to drag it.
I suggest you 2 easy ways to solve your problem.
1) Add a DragListener to your actor:
actor.addListener(new DragListener() {
public void drag(InputEvent event, float x, float y, int pointer) {
actor.moveBy(x - actor.getWidth() / 2, y - actor.getHeight() / 2);
}
});
2) Create a generic actor which size is filled to the stage, and use it as the target actor.

Converting Camera Coordinates to Custom View Coordinates

I am trying to make a simple face detection app consisting of a SurfaceView (essentially a camera preview) and a custom View (for drawing purposes) stacked on top. The two views are essentially the same size, stacked on one another in a RelativeLayout. When a person's face is detected, I want to draw a white rectangle on the custom View around their face.
The Camera.Face.rect object returns the face bound coordinates using the coordinate system explained here and the custom View uses the coordinate system described in the answer to this question. Some sort of conversion is needed before I can use it to draw on the canvas.
Therefore, I wrote an additional method ScaleFacetoView() in my custom view class (below) I redraw the custom view every time a face is detected by overriding the OnFaceDetection() method. The result is the white box appears correctly when a face is in the center. The problem I noticed is that it does not correct track my face when it moves to other parts of the screen.
Namely, if I move my face:
Up - the box goes left
Down - the box goes right
Right - the box goes upwards
Left - the box goes down
I seem to have incorrectly mapped the values when scaling the coordinates. Android docs provide this method of converting using a matrix, but it is rather confusing and I have no idea what it is doing. Can anyone provide some code on the correct way of converting Camera.Face coordinates to View coordinates?
Here's the code for my ScaleFacetoView() method.
public void ScaleFacetoView(Face[] data, int width, int height, TextView a){
//Extract data from the face object and accounts for the 1000 value offset
mLeft = data[0].rect.left + 1000;
mRight = data[0].rect.right + 1000;
mTop = data[0].rect.top + 1000;
mBottom = data[0].rect.bottom + 1000;
//Compute the scale factors
float xScaleFactor = 1;
float yScaleFactor = 1;
if (height > width){
xScaleFactor = (float) width/2000.0f;
yScaleFactor = (float) height/2000.0f;
}
else if (height < width){
xScaleFactor = (float) height/2000.0f;
yScaleFactor = (float) width/2000.0f;
}
//Scale the face parameters
mLeft = mLeft * xScaleFactor; //X-coordinate
mRight = mRight * xScaleFactor; //X-coordinate
mTop = mTop * yScaleFactor; //Y-coordinate
mBottom = mBottom * yScaleFactor; //Y-coordinate
}
As mentioned above, I call the custom view like so:
#Override
public void onFaceDetection(Face[] arg0, Camera arg1) {
if(arg0.length == 1){
//Get aspect ratio of the screen
View parent = (View) mRectangleView.getParent();
int width = parent.getWidth();
int height = parent.getHeight();
//Modify xy values in the view object
mRectangleView.ScaleFacetoView(arg0, width, height);
mRectangleView.setInvalidate();
//Toast.makeText( cc ,"Redrew the face.", Toast.LENGTH_SHORT).show();
mRectangleView.setVisibility(View.VISIBLE);
//rest of code
Using the explanation Kenny gave I manage to do the following.
This example works using the front facing camera.
RectF rectF = new RectF(face.rect);
Matrix matrix = new Matrix();
matrix.setScale(1, 1);
matrix.postScale(view.getWidth() / 2000f, view.getHeight() / 2000f);
matrix.postTranslate(view.getWidth() / 2f, view.getHeight() / 2f);
matrix.mapRect(rectF);
The returned Rectangle by the matrix has all the right coordinates to draw into the canvas.
If you are using the back camera I think is just a matter of changing the scale to:
matrix.setScale(-1, 1);
But I haven't tried that.
The Camera.Face class returns the face bound coordinates using the image frame that the phone would save into its internal storage, rather than using the image displayed in the Camera Preview. In my case, the images were saved in a different manner from the camera, resulting in a incorrect mapping. I had to manually account for the discrepancy by taking the coordinates, rotating it counter clockwise 90 degrees and flipping it on the y-axis prior to scaling it to the canvas used for the custom view.
EDIT:
It would also appear that you can't change the way the face bound coordinates are returned by modifying the camera capture orientation using the Camera.Parameters.setRotation(int) method either.

Android 4.3 ImageView ScaleType.MATRIX

today I set up the new Android JB 4.3 on my Nexus 7 and i tried to run my application.
Everythings works like it should except one little thing about ImageViews with ScaleType.MATRIX.
Basically what i have in my application is a ImageView as background and accordingly to a ViewPager callbacks i move the focused part of the image updating the Matrix i gave to the imageView using setImageMatix( Matrix matrix ).
the problem seems to be that i can't update the matrix anymore, i just have to instantiate a new one a pass it to the ImageView.
i managed to work around it instantiating everytime a new Matrix but it seems awfully memory expensive compared to the old version.
is this a BUG?
is there a way to udpate the Matrix? ( i by the way already tried to invalidate() the ImageView ecc. )
NOT WORKING
private void updateMatrix( final int page, final double offset ) {
double pagePosition = page + offset;
Matrix matrix = imageView.getImageMatrix();
matrix.setScale( scale, scale );
matrix.postTranslate( - (float) ( pagePosition * pageWidth ) , 0 );
imageView.setImageMatrix( matrix );
imageView.invalidate();
}
WORKING
private void updateMatrix( final int page, final double offset ) {
double pagePosition = page + offset;
Matrix matrix = new Matrix();
matrix.setScale( scale, scale );
matrix.postTranslate( - (float) ( pagePosition * pageWidth ) , 0 );
imageView.setImageMatrix( matrix );
imageView.invalidate();
}
EDIT:
in the first case the image is shown at the top left corner of the ImageView without any scale or translate applied to it, like if the matrix is back to identity.
Just preserve your Matrix as field instead of retrieving it from ImageView and you'll be happy :)
There may be a bug with ImageView scaling starting with 4.3. See my question and answer about this bug.

Categories

Resources