World!
I'm using Harism Page Curl to implement page curl in my project all thing are ok but the direction of curling.
I'm using arabic language in my app so the curl must be from Left to Right(Arabic books).
what this library offer is curling from right to left (english books).
so i tried the following with no succeed:
Reversing the image loading.
Changing parameters in CurlView Class.
as shown below :
public class CurlView extends GLSurfaceView implements View.OnTouchListener,
CurlRenderer.Observer {
// Shows one page at the center of view.
public static final int SHOW_ONE_PAGE = 1;
// Shows two pages side by side.
public static final int SHOW_TWO_PAGES = 2;
// Curl state. We are flipping none, left or right page.
private static final int CURL_LEFT = 1;
private static final int CURL_NONE = 0;
private static final int CURL_RIGHT = 2;
// Constants for mAnimationTargetEvent.
private static final int SET_CURL_TO_LEFT = 1;
private static final int SET_CURL_TO_RIGHT = 2;
private boolean mAllowLastPageCurl = true;
private boolean mAnimate = false;
private long mAnimationDurationTime = 300;
private PointF mAnimationSource = new PointF();
private long mAnimationStartTime;
private PointF mAnimationTarget = new PointF();
private int mAnimationTargetEvent;
private PointF mCurlDir = new PointF();
private PointF mCurlPos = new PointF();
private int mCurlState = CURL_NONE;
// Current bitmap index. This is always showed as front of right page.
private int mCurrentIndex = 0;
// Start position for dragging.
private PointF mDragStartPos = new PointF();
private boolean mEnableTouchPressure = false;
// Bitmap size. These are updated from renderer once it's initialized.
private int mPageBitmapHeight = -1;
private int mPageBitmapWidth = -1;
// Page meshes. Left and right meshes are 'static' while curl is used to
// show page flipping.
private CurlMesh mPageCurl;
private CurlMesh mPageLeft;
private PageProvider mPageProvider;
private CurlMesh mPageRight;
private PointerPosition mPointerPos = new PointerPosition();
private CurlRenderer mRenderer;
private boolean mRenderLeftPage = true;
private SizeChangedObserver mSizeChangedObserver;
// One page is the default.
private int mViewMode = SHOW_ONE_PAGE;`
and
#Override
public int getPageCount() {
return mBitmapIds.length;
}
public Bitmap loadBitmap(int width, int height, int index) {
tracker.send(new HitBuilders.EventBuilder()
.setCategory("UX")
.setAction("click")
.setLabel("submit")
.build());
Bitmap b = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
b.eraseColor(Color.WHITE);
Canvas c = new Canvas(b);
Drawable d = getResources().getDrawable(mBitmapIds[index]);
int margin = 0;
int border = 0;
Rect r = new Rect(margin, margin, width, height);
int imageWidth = r.width() - (border);
assert d != null;
int imageHeight = imageWidth * d.getIntrinsicHeight()
/ d.getIntrinsicWidth();
if (imageHeight > r.height() - (border)) {
imageHeight = r.height() - (border);
imageWidth = imageHeight * d.getIntrinsicWidth()
/ d.getIntrinsicHeight();
}
r.left += ((r.width() - imageWidth));
r.right = r.left + imageWidth + border;
r.top += r.top;
Paint p = new Paint();
p.setColor(0xFFC0C0C0);
c.drawRect(r, p);
r.left += border;
r.right -= border;
r.top += border;
r.bottom -= border;
d.setBounds(r);
d.draw(c);
return b;
}
#Override
public void updatePage(CurlPage page, int width, int height, int index) {
if (index == i) {
Bitmap back = loadBitmap(width, height, index);
page.setTexture(back, CurlPage.SIDE_BOTH);
index++;
i++;
} else {
Bitmap back = loadBitmap(width, height, index);
page.setTexture(back, CurlPage.SIDE_BOTH);
}
}
Related
My UI designer has come up with a design like this for a progress bar:
The numbers should be the progress and max.
The circle image will change. On some of the designs there is also an image next to the 1500.
Whenever I try to do this on a layer-list I always end up with the image in the middle of the drawable. Ideally I would prefer to use vector graphics but I can use png if needed. I haven't even looked at putting the numbers there yet.
So how can this be accomplished?
Thank you.
Using canvas seems to me easier for this case. Here a short sample i could come up with right now:
public class Loading extends View {
private final static float VIEW_HEIGHT = 80;
private RectF viewRectangle;
private RectF progressRectangle;
private float cornersRadius;
private Paint progressBarPaint;
private Paint progressTextPaint;
private Paint containerBarPaint;
private Paint containerTextPaint;
private final int progressMaxValue = 1500;
private float containerTextY;
private float containerTextX;
private final float whiteCircleRadius = 14;
private final float progressTextPadding = 16;
private float progress;
public Loading(Context context) {
super(context);
progress = 0.5f;
progressTextPaint = new Paint(LINEAR_TEXT_FLAG|SUBPIXEL_TEXT_FLAG|ANTI_ALIAS_FLAG);
progressTextPaint.setColor(Color.WHITE);
progressTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
progressTextPaint.setTextSize(28);
progressTextPaint.setStrokeWidth(1f);
containerTextPaint = new Paint(progressTextPaint);
containerTextPaint.setColor(Color.BLACK);
progressBarPaint = new Paint(ANTI_ALIAS_FLAG);
progressBarPaint.setColor(Color.BLUE);
progressBarPaint.setStyle(Paint.Style.FILL);
containerBarPaint = new Paint(ANTI_ALIAS_FLAG);
containerBarPaint.setColor(Color.GRAY);
containerBarPaint.setStyle(Paint.Style.FILL);
}
#Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
int horizontalPadding = getPaddingLeft() + getPaddingRight();
int verticalPadding = getPaddingTop() + getPaddingBottom();
float measuredHeight = height - verticalPadding;
float targetHeight = measuredHeight < VIEW_HEIGHT ? measuredHeight : VIEW_HEIGHT;
float containerWidth = width - horizontalPadding;
viewRectangle = new RectF(getPaddingLeft(), getPaddingTop(), containerWidth, targetHeight);
progressRectangle = new RectF(viewRectangle);
cornersRadius = targetHeight / 2;
String maxValueText = String.valueOf(progressMaxValue);
Rect containerTextBounds = new Rect();
containerTextPaint.getTextBounds(maxValueText, 0, maxValueText.length(), containerTextBounds);
containerTextX = viewRectangle.right - containerTextBounds.width() - cornersRadius / 2;
containerTextY = viewRectangle.centerY() - containerTextBounds.exactCenterY();
}
#Override
protected void onDraw(Canvas canvas) {
float progressWidth = viewRectangle.right * progress;
float cornerDiameter = cornersRadius * 2;
progressRectangle.right = progressWidth > cornerDiameter ? progressWidth : cornerDiameter;
canvas.drawRoundRect(viewRectangle, cornersRadius, cornersRadius, containerBarPaint);
canvas.drawRoundRect(progressRectangle, cornersRadius, cornersRadius, progressBarPaint);
canvas.drawCircle(progressRectangle.right - cornersRadius, progressRectangle.centerY(), whiteCircleRadius, progressTextPaint);
canvas.drawText(String.valueOf(progressMaxValue), containerTextX, containerTextY, containerTextPaint);
String progressText = String.valueOf((int) (progressMaxValue * progress));
float progressTextWidth = progressTextPaint.measureText(progressText);
if (progressTextWidth < progressRectangle.right * 2) {
float requiredProgressTextSpace = cornersRadius + whiteCircleRadius + progressTextPadding + progressTextWidth;
canvas.drawText(progressText, progressRectangle.right - requiredProgressTextSpace, containerTextY, progressTextPaint);
}
}
}
It's far from perfect and not very flexible, but a good place to start with. If you need some comments here, feel free to ask. Here the render of the code above:
I'm using KenBurnsView to add animation to my image.
Is it possible to set the max scale programmatically ? Small images are too zooming.
Yes, you can . For this purpose you have to implement your own TransitionGenerator.
Like given blow .In following code you can call SetMinRectFactor() to set minimum zoom sacale.
public class BackgroundTransitionGenerator implements TransitionGenerator
{
private static final int DEFAULT_TRANSITION_DURATION = 9000;
private static final Interpolator DEFAULT_TRANSITION_INTERPOLATOR =
new LinearInterpolator();
private long transitionDuration;
private Interpolator transitionInterpolator;
private Transition lastTransition;
private RectF lastDrawableBounds;
private boolean forward;
private float MIN_RECT_FACTOR=1.0f;
public void SetMinRectFactor(float f)
{
MIN_RECT_FACTOR=f;
}
public BackgroundTransitionGenerator() {
transitionDuration = DEFAULT_TRANSITION_DURATION;
transitionInterpolator = DEFAULT_TRANSITION_INTERPOLATOR;
}
#Override
public Transition generateNextTransition(RectF drawableBounds, RectF viewport) {
float drawableRatio = getRectRatio(drawableBounds);
float viewportRectRatio = getRectRatio(viewport);
RectF startRect;
RectF endRect;
if (drawableRatio >= viewportRectRatio) {
float w = drawableBounds.height() * viewportRectRatio;
float h = drawableBounds.height();
startRect = new RectF(0, 0, w, h);
endRect =generateRandomRect(drawableBounds,viewport); //new RectF((drawableBounds.width() - w), drawableBounds.height(),drawableBounds.width(), h);
} else {
float w = drawableBounds.width();
float h = drawableBounds.width() / viewportRectRatio;
startRect = new RectF(0, 0, w, h);
endRect =generateRandomRect(drawableBounds,viewport); //new RectF(0, drawableBounds.height() - h, w, drawableBounds.height());
}
if (!drawableBounds.equals(lastDrawableBounds) || !haveSameAspectRatio(lastTransition.getDestinyRect(), viewport)) {
forward = false;
}
forward = !forward;
if (forward) {
lastTransition = new Transition(startRect, endRect, transitionDuration, transitionInterpolator);
} else {
lastTransition = new Transition(endRect, startRect, transitionDuration, transitionInterpolator);
}
lastDrawableBounds = new RectF(drawableBounds);
return lastTransition;
}
private static boolean haveSameAspectRatio(RectF r1, RectF r2) {
return (Math.abs(getRectRatio(r1) - getRectRatio(r2)) <= 0.01f);
}
private RectF generateRandomRect(RectF drawableBounds, RectF viewportRect) {
float drawableRatio = getRectRatio(drawableBounds);
float viewportRectRatio = getRectRatio(viewportRect);
RectF maxCrop;
if (drawableRatio > viewportRectRatio) {
float r = (drawableBounds.height() / viewportRect.height()) * viewportRect.width();
float b = drawableBounds.height();
maxCrop = new RectF(0, 0, r, b);
} else {
float r = drawableBounds.width();
float b = (drawableBounds.width() / viewportRect.width()) * viewportRect.height();
maxCrop = new RectF(0, 0, r, b);
}
float factor = MIN_RECT_FACTOR ;
float width = factor * maxCrop.width();
float height = factor * maxCrop.height();
int widthDiff = (int) (drawableBounds.width() - width);
int heightDiff = (int) (drawableBounds.height() - height);
int left = widthDiff;
int top = heightDiff;
return new RectF(left, top, left + width, top + height);
}
private static float getRectRatio(RectF rect) {
return rect.width() / rect.height();
}
}
I have created a donut chart, which is shown below:
MY resultant Donut chart should be in the following way:
My Question is, How can i achieve the lines with image (They are rounded off in second screen shot)
For reference, Here is the code which I have written:
public class PieChartView extends View {
private int[] values = {30, 60, 90, 100, 150};
private int c[] = {Color.MAGENTA,Color.BLUE,Color.RED,Color.CYAN,Color.YELLOW};
private int valuesLength = values.length;
private RectF rectF;
private Paint slicePaint, textPaint;
private Path path;
public PieChartView(Context context, AttributeSet attrs) {
super(context, attrs);
valuesLength = values.length;
slicePaint = new Paint();
slicePaint.setAntiAlias(true);
slicePaint.setDither(true);
slicePaint.setStyle(Paint.Style.FILL);
path = new Path();
}
#SuppressLint("DrawAllocation")
#Override
protected void onDraw(Canvas canvas) {
if(values != null) {
int startTop = 0;
int startLeft = 0;
int endBottom = getHeight();
int endRight = endBottom;// This makes an equal square.
rectF = new RectF(startLeft, startTop, endRight, endBottom);
float[] scaledValues = scale();
float sliceStartPoint = 0;
path.addCircle(rectF.centerX(), rectF.centerY(), 125, Direction.CW);
canvas.clipPath(path, Op.DIFFERENCE);
for(int i = 0; i < valuesLength; i++) {
slicePaint.setColor(c[i]);
path.reset();
path.addArc(rectF, sliceStartPoint, scaledValues[i]);
path.lineTo(rectF.centerX(), rectF.centerY());
canvas.drawPath(path, slicePaint);
sliceStartPoint += scaledValues[i];//This updates the starting point of next slice.
}
}
}
private float[] scale() {
float[] scaledValues = new float[this.values.length];
float total = getTotal(); //Total all values supplied to the chart
for (int i = 0; i < this.values.length; i++) {
scaledValues[i] = (this.values[i] / total) * 360; //Scale each value
}
return scaledValues;
}
private float getTotal() {
float total = 0;
for (float val : this.values)
total += val;
return total;
}
}
Also, How can I find out a co-ordinate from an angle(Start or sweep angle). If i want to draw a line from centre of a circle to the coordinate?
Here's how i finally did it after two days of search with help of this library https://github.com/Ken-Yang/AndroidPieChart
And equations to center text done with help of my friends and alot of search
on MainActivity onCreate or oncreateView if you are using fragments:
PieChart pie = (PieChart) rootView.findViewById(R.id.pieChart);
ArrayList<Float> alPercentage = new ArrayList<Float>();
alPercentage.add(2.0f);
alPercentage.add(8.0f);
alPercentage.add(20.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.85f);
alPercentage.add(9.15f);
try {
// setting data
pie.setAdapter(alPercentage);
// setting a listener
pie.setOnSelectedListener(new OnSelectedLisenter() {
#Override
public void onSelected(int iSelectedIndex) {
Toast.makeText(getActivity(),
"Select index:" + iSelectedIndex,
Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
if (e.getMessage().equals(PieChart.ERROR_NOT_EQUAL_TO_100)) {
Log.e("kenyang", "percentage is not equal to 100");
}
}
public class PieChart extends View {
public interface OnSelectedLisenter {
public abstract void onSelected(int iSelectedIndex);
}
private OnSelectedLisenter onSelectedListener = null;
private static final String TAG = PieChart.class.getName();
public static final String ERROR_NOT_EQUAL_TO_100 = "NOT_EQUAL_TO_100";
private static final int DEGREE_360 = 360;
private static String[] PIE_COLORS = null;
private static int iColorListSize = 0;
ArrayList<Float> array;
private Paint paintPieFill;
private Paint paintPieBorder;
private Paint paintCenterCircle;
private ArrayList<Float> alPercentage = new ArrayList<Float>();
private int mCenterX = 320;
private int mCenterY = 320;
private int iDisplayWidth, iDisplayHeight;
private int iSelectedIndex = -1;
private int iCenterWidth = 0;
private int iShift = 0;
private int iMargin = 0; // margin to left and right, used for get Radius
private int iDataSize = 0;
private Canvas canvas1;
private RectF r = null;
private RectF centerCircle = null;
private float fDensity = 0.0f;
private float fStartAngle = 0.0f;
private float fEndAngle = 0.0f;
float fX;
float fY;
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
PIE_COLORS = getResources().getStringArray(R.array.colors);
iColorListSize = PIE_COLORS.length;
array = new ArrayList<Float>();
fnGetDisplayMetrics(context);
iShift = (int) fnGetRealPxFromDp(30);
iMargin = (int) fnGetRealPxFromDp(40);
centerCircle = new RectF(200, 200, 440, 440);
// used for paint circle
paintPieFill = new Paint(Paint.ANTI_ALIAS_FLAG);
paintPieFill.setStyle(Paint.Style.FILL);
// used for paint centerCircle
paintCenterCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
paintCenterCircle.setStyle(Paint.Style.FILL);
paintCenterCircle.setColor(Color.WHITE);
// used for paint border
paintPieBorder = new Paint(Paint.ANTI_ALIAS_FLAG);
paintPieBorder.setStyle(Paint.Style.STROKE);
paintPieBorder.setStrokeWidth(fnGetRealPxFromDp(3));
paintPieBorder.setColor(Color.WHITE);
Log.i(TAG, "PieChart init");
}
// set listener
public void setOnSelectedListener(OnSelectedLisenter listener) {
this.onSelectedListener = listener;
}
float temp = 0;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i(TAG, "onDraw");
float centerX = (r.left + r.right) / 2;
float centerY = (r.top + r.bottom) / 2;
float radius1 = (r.right - r.left) / 2;
radius1 *= 0.5;
float startX = mCenterX;
float startY = mCenterY;
float radius = mCenterX;
float medianAngle = 0;
Path path = new Path();
for (int i = 0; i < iDataSize; i++) {
// check whether the data size larger than color list size
if (i >= iColorListSize) {
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i
% iColorListSize]));
} else {
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i]));
}
fEndAngle = alPercentage.get(i);
// convert percentage to angle
fEndAngle = fEndAngle / 100 * DEGREE_360;
// if the part of pie was selected then change the coordinate
if (iSelectedIndex == i) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
float fAngle = fStartAngle + fEndAngle / 2;
double dxRadius = Math.toRadians((fAngle + DEGREE_360)
% DEGREE_360);
fY = (float) Math.sin(dxRadius);
fX = (float) Math.cos(dxRadius);
canvas.translate(fX * iShift, fY * iShift);
}
canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieFill);
float angle = (float) ((fStartAngle + fEndAngle / 2) * Math.PI / 180);
float stopX = (float) (startX + (radius/2) * Math.cos(angle));
float stopY = (float) (startY + (radius/2) * Math.sin(angle));
// if the part of pie was selected then draw a border
if (iSelectedIndex == i) {
canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieBorder);
canvas.drawLine(startX, startY, stopX, stopY, paintPieFill);
canvas.restore();
}
fStartAngle = fStartAngle + fEndAngle;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// get screen size
iDisplayWidth = MeasureSpec.getSize(widthMeasureSpec);
iDisplayHeight = MeasureSpec.getSize(heightMeasureSpec);
if (iDisplayWidth > iDisplayHeight) {
iDisplayWidth = iDisplayHeight;
}
/*
* determine the rectangle size
*/
iCenterWidth = iDisplayWidth / 2;
int iR = iCenterWidth - iMargin;
if (r == null) {
r = new RectF(iCenterWidth - iR, // top
iCenterWidth - iR, // left
iCenterWidth + iR, // right
iCenterWidth + iR); // bottom
}
if (centerCircle == null) {
// centerCircle=new RectF(left, top, right, bottom);
}
setMeasuredDimension(iDisplayWidth, iDisplayWidth);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// get degree of the touch point
double dx = Math.atan2(event.getY() - iCenterWidth, event.getX()
- iCenterWidth);
float fDegree = (float) (dx / (2 * Math.PI) * DEGREE_360);
fDegree = (fDegree + DEGREE_360) % DEGREE_360;
// get the percent of the selected degree
float fSelectedPercent = fDegree * 100 / DEGREE_360;
// check which pie was selected
float fTotalPercent = 0;
for (int i = 0; i < iDataSize; i++) {
fTotalPercent += alPercentage.get(i);
if (fTotalPercent > fSelectedPercent) {
iSelectedIndex = i;
break;
}
}
if (onSelectedListener != null) {
onSelectedListener.onSelected(iSelectedIndex);
}
invalidate();
return super.onTouchEvent(event);
}
private void fnGetDisplayMetrics(Context cxt) {
final DisplayMetrics dm = cxt.getResources().getDisplayMetrics();
fDensity = dm.density;
}
private float fnGetRealPxFromDp(float fDp) {
return (fDensity != 1.0f) ? fDensity * fDp : fDp;
}
public void setAdapter(ArrayList<Float> alPercentage) throws Exception {
this.alPercentage = alPercentage;
iDataSize = alPercentage.size();
float fSum = 0;
for (int i = 0; i < iDataSize; i++) {
fSum += alPercentage.get(i);
}
if (fSum != 100) {
Log.e(TAG, ERROR_NOT_EQUAL_TO_100);
iDataSize = 0;
throw new Exception(ERROR_NOT_EQUAL_TO_100);
}
}
<com.example.piecharts.PieChart
android:id="#+id/pieChart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.example.piecharts.PieChart>
I would like to make vertical 3d list view like here, but for ImageButtons and for free. Is there any library or sample code for that? I am new in Android development, so I don't know how to animate such thing
its actually pretty simple. You need to extend ListView and override onDrawChild(). In there you can apply 3d transformation matrices to get the effect you want.
I have a working example on my github
Or you can have a look at this question which is quite similar.
For your convenience this is my implementation of a 3d ListView:
public class ListView3d extends ListView {
/** Ambient light intensity */
private static final int AMBIENT_LIGHT = 55;
/** Diffuse light intensity */
private static final int DIFFUSE_LIGHT = 200;
/** Specular light intensity */
private static final float SPECULAR_LIGHT = 70;
/** Shininess constant */
private static final float SHININESS = 200;
/** The max intensity of the light */
private static final int MAX_INTENSITY = 0xFF;
private final Camera mCamera = new Camera();
private final Matrix mMatrix = new Matrix();
/** Paint object to draw with */
private Paint mPaint;
public ListView3d(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
// get top left coordinates
final int top = child.getTop();
final int left = child.getLeft();
Bitmap bitmap = child.getDrawingCache();
if (bitmap == null) {
child.setDrawingCacheEnabled(true);
child.buildDrawingCache();
bitmap = child.getDrawingCache();
}
final int centerY = child.getHeight() / 2;
final int centerX = child.getWidth() / 2;
final int radius = getHeight() / 2;
final int absParentCenterY = getTop() + getHeight() / 2;
final int absChildCenterY = child.getTop() + centerX;
final int distanceY = absParentCenterY - absChildCenterY;
final int absDistance = Math.min(radius, Math.abs(distanceY));
final float translateZ = (float) Math.sqrt((radius * radius) - (absDistance * absDistance));
double radians = Math.acos((float) absDistance / radius);
double degree = 90 - (180 / Math.PI) * radians;
mCamera.save();
mCamera.translate(0, 0, radius - translateZ);
mCamera.rotateX((float) degree); // remove this line..
if (distanceY < 0) {
degree = 360 - degree;
}
mCamera.rotateY((float) degree); // and change this to rotateX() to get a
// wheel like effect
mCamera.getMatrix(mMatrix);
mCamera.restore();
// create and initialize the paint object
if (mPaint == null) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setFilterBitmap(true);
}
//highlight elements in the middle
mPaint.setColorFilter(calculateLight((float) degree));
mMatrix.preTranslate(-centerX, -centerY);
mMatrix.postTranslate(centerX, centerY);
mMatrix.postTranslate(left, top);
canvas.drawBitmap(bitmap, mMatrix, mPaint);
return false;
}
private LightingColorFilter calculateLight(final float rotation) {
final double cosRotation = Math.cos(Math.PI * rotation / 180);
int intensity = AMBIENT_LIGHT + (int) (DIFFUSE_LIGHT * cosRotation);
int highlightIntensity = (int) (SPECULAR_LIGHT * Math.pow(cosRotation, SHININESS));
if (intensity > MAX_INTENSITY) {
intensity = MAX_INTENSITY;
}
if (highlightIntensity > MAX_INTENSITY) {
highlightIntensity = MAX_INTENSITY;
}
final int light = Color.rgb(intensity, intensity, intensity);
final int highlight = Color.rgb(highlightIntensity, highlightIntensity, highlightIntensity);
return new LightingColorFilter(light, highlight);
}
}
Cheers
I've some sample code that comes with Android that distorts a bitmap image(Bitmapmesh.java). I'm wanting a circle placed on my image that gives a fisheye effect. I'm new to android and especially graphics, is it possible to create this effect in the bitmapmesh sample?
I'm not sure where to start with this so any pointers would be appreciated. Can anyone give me a high level view of what's involved, eg i'd like to place a circle on the image firstly. i've placed buttons over images before that seem to float, this was done by using a relative layout then adding child buttons. what i'm tring to do now is different and will probably involve calling some onDraw method? i also have an algorithm that does the distortion, i'm just not sure how to apply this to the image.
Below is the bitmapmesh code. Can anyone talk me through where to start, even if it's just placing the circle on the image first, then i can tackle implementing the effect.
thanks mat
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import android.content.Context;
import android.graphics.;
import android.os.Bundle;
import android.os.Environment;
import android.view.;
import android.util.FloatMath;
public class BitMapFishEye extends GraphicsActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
private static final int WIDTH = 20;
private static final int HEIGHT = 20;
private static final int COUNT = (WIDTH + 1) * (HEIGHT + 1);
private final Bitmap mBitmap;
private final float[] mVerts = new float[COUNT*2];
private final float[] mOrig = new float[COUNT*2];
private final Matrix mMatrix = new Matrix();
private final Matrix mInverse = new Matrix();
private File tempFile;
private byte[] imageArray;
private static void setXY(float[] array, int index, float x, float y) {
array[index*2 + 0] = x;
array[index*2 + 1] = y;
}
public SampleView(Context context) {
super(context);
setFocusable(true);
/* mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.beach);*/
tempFile = new File(Environment.getExternalStorageDirectory().
getAbsolutePath() + "/"+"image.jpg");
imageArray = new byte[(int)tempFile.length()];
try{
InputStream is = new FileInputStream(tempFile);
BufferedInputStream bis = new BufferedInputStream(is);
DataInputStream dis = new DataInputStream(bis);
int i = 0;
while (dis.available() > 0) {
imageArray[i] = dis.readByte();
i++;
}
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 5;
mBitmap = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
float w = mBitmap.getWidth();
float h = mBitmap.getHeight();
// construct our mesh
int index = 0;
for (int y = 0; y <= HEIGHT; y++) {
float fy = h * y / HEIGHT;
for (int x = 0; x <= WIDTH; x++) {
float fx = w * x / WIDTH;
setXY(mVerts, index, fx, fy);
setXY(mOrig, index, fx, fy);
index += 1;
}
}
mMatrix.setTranslate(10, 10);
mMatrix.invert(mInverse);
}
#Override protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
canvas.concat(mMatrix);
canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0,
null, 0, null);
}
private void warp(float cx, float cy) {
final float K = 10000;
float[] src = mOrig;
float[] dst = mVerts;
for (int i = 0; i < COUNT*2; i += 2) {
float x = src[i+0];
float y = src[i+1];
float dx = cx - x;
float dy = cy - y;
float dd = dx*dx + dy*dy;
float d = FloatMath.sqrt(dd);
float pull = K / (dd + 0.000001f);
pull /= (d + 0.000001f);
// android.util.Log.d("skia", "index " + i + " dist=" + d + " pull=" + pull);
if (pull >= 1) {
dst[i+0] = cx;
dst[i+1] = cy;
} else {
dst[i+0] = x + dx * pull;
dst[i+1] = y + dy * pull;
}
}
}
private int mLastWarpX = -9999; // don't match a touch coordinate
private int mLastWarpY;
#Override public boolean onTouchEvent(MotionEvent event) {
float[] pt = { event.getX(), event.getY() };
mInverse.mapPoints(pt);
int x = (int)pt[0];
int y = (int)pt[1];
if (mLastWarpX != x || mLastWarpY != y) {
mLastWarpX = x;
mLastWarpY = y;
warp(pt[0], pt[1]);
invalidate();
}
return true;
}
}
}