I have five shape draw able rectangular, I have to set the rectangle at angle of (-20,-15,-10,-5,0)Degree. Each Rectangular have four colors shade. Now I need to animate each rectangle one by one and if user drag left to right then top rectangle moves to left to right.
Problem is, I can’t move each rectangle separately. How I can identify and implement each rectangle separately?
Here sample snapshot that i have to do.
http://postimage.org/image/13sa96sbo/
public ColorFanDraw(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvasObject) {
int x = 100;
int y = 50;
int width = 70;
int convasSize =200;
Paint thePaint = new Paint();
thePaint.setColor(mTouchedColor-200);
canvasObject.rotate(-15, centerX,centerY);
canvasObject.drawRect(new Rect(x,y,x+width,y+convasSize), thePaint);
thePaint.setColor(mTouchedColor-50);
canvasObject.rotate(10, centerX,centerY);
canvasObject.drawRect(new Rect(x,y,x+width,y+convasSize), thePaint);
canvasObject.rotate(10, centerX,centerY);
thePaint.setColor(mTouchedColor);
canvasObject.drawRect(new Rect(x,y,x+width,y+convasSize), thePaint);
rotation = AnimationUtils.loadAnimation(contextObj,
R.anim.view_transition_in_left);
ImageView img = new ImageView(contextObj);
img.startAnimation(rotation);
}
You would need to store the rectangle objects in a variable before you draw them onto the Canvas.
Rect rectangle1 = new Rect(x,y,x+width,y+convasSize);
canvasObject.drawRect(rectangel1, thePaint);
Rect rectangle2 = new Rect(x,y,x+width,y+convasSize);
canvasObject.drawRect(rectangel2, thePaint);
and so on.
Then you can refer to the individual rectangles wherever you are doing your animation.
Related
How can we achieve the fade-out effect on the last line of a TextView, like in the "WHAT'S NEW" section in the Play Store app?
That fade effect can be accomplished by subclassing a TextView class to intercept its draw, and doing something like what the View class does to fade out edges, but only in the last stretch of the final text line.
In this example, we create a unit horizontal linear gradient that goes from transparent to solid black. As we prepare to draw, this unit gradient is scaled to a length calculated as a simple fraction of the TextView's final line length, and then positioned accordingly.
An off-screen buffer is created, and we let the TextView draw its content to that. We then draw the fade gradient over it with a transfer mode of PorterDuff.Mode.DST_OUT, which essentially clears the underlying content to a degree relative to the gradient's opacity at a given point. Drawing that buffer back on-screen results in the desired fade, no matter what is in the background.
public class FadingTextView extends AppCompatTextView {
private static final float FADE_LENGTH_FACTOR = .4f;
private final RectF drawRect = new RectF();
private final Rect realRect = new Rect();
private final Path selection = new Path();
private final Matrix matrix = new Matrix();
private final Paint paint = new Paint();
private final Shader shader =
new LinearGradient(0f, 0f, 1f, 0f, 0x00000000, 0xFF000000, Shader.TileMode.CLAMP);
public FadingTextView(Context context) {
this(context, null);
}
public FadingTextView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
}
public FadingTextView(Context context, AttributeSet attrs, int defStyleAttribute) {
super(context, attrs, defStyleAttribute);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
#Override
protected void onDraw(Canvas canvas) {
// Locals
final RectF drawBounds = drawRect;
final Rect realBounds = realRect;
final Path selectionPath = selection;
final Layout layout = getLayout();
// Figure last line index, and text offsets there
final int lastLineIndex = getLineCount() - 1;
final int lastLineStart = layout.getLineStart(lastLineIndex);
final int lastLineEnd = layout.getLineEnd(lastLineIndex);
// Let the Layout figure a Path that'd cover the last line text
layout.getSelectionPath(lastLineStart, lastLineEnd, selectionPath);
// Convert that Path to a RectF, which we can more easily modify
selectionPath.computeBounds(drawBounds, false);
// Naive text direction determination; may need refinement
boolean isRtl =
layout.getParagraphDirection(lastLineIndex) == Layout.DIR_RIGHT_TO_LEFT;
// Narrow the bounds to just the fade length
if (isRtl) {
drawBounds.right = drawBounds.left + drawBounds.width() * FADE_LENGTH_FACTOR;
} else {
drawBounds.left = drawBounds.right - drawBounds.width() * FADE_LENGTH_FACTOR;
}
// Adjust for drawables and paddings
drawBounds.offset(getTotalPaddingLeft(), getTotalPaddingTop());
// Convert drawing bounds to real bounds to determine
// if we need to do the fade, or a regular draw
drawBounds.round(realBounds);
realBounds.offset(-getScrollX(), -getScrollY());
boolean needToFade = realBounds.intersects(getTotalPaddingLeft(), getTotalPaddingTop(),
getWidth() - getTotalPaddingRight(), getHeight() - getTotalPaddingBottom());
if (needToFade) {
// Adjust and set the Shader Matrix
final Matrix shaderMatrix = matrix;
shaderMatrix.reset();
shaderMatrix.setScale(drawBounds.width(), 1f);
if (isRtl) {
shaderMatrix.postRotate(180f, drawBounds.width() / 2f, 0f);
}
shaderMatrix.postTranslate(drawBounds.left, drawBounds.top);
shader.setLocalMatrix(shaderMatrix);
// Save, and start drawing to an off-screen buffer
final int saveCount;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
saveCount = canvas.saveLayer(null, null);
} else {
saveCount = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG);
}
// Let TextView draw itself to the buffer
super.onDraw(canvas);
// Draw the fade to the buffer, over the TextView content
canvas.drawRect(drawBounds, paint);
// Restore, and draw the buffer back to the Canvas
canvas.restoreToCount(saveCount);
} else {
// Regular draw
super.onDraw(canvas);
}
}
}
This is a drop-in replacement for TextView, and you'd use it in your layout similarly.
<com.example.app.FadingTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#e2f3eb"
android:textColor="#0b8043"
android:lineSpacingMultiplier="1.2"
android:text="#string/umang" />
Notes:
The fade length calculation is based on a constant fraction of the final line's text length, here determined by FADE_LENGTH_FACTOR. This seems to be the same basic methodology of the Play Store component, as the absolute length of the fade appears to vary with line length. The FADE_LENGTH_FACTOR value can be altered as desired.
FadingTextView currently extends AppCompatTextView, but it works perfectly well as a plain TextView, if you should need that instead. I would think that it will work as a MaterialTextView too, though I've not tested that thoroughly.
This example is geared mainly toward relatively plain use; i.e., as a simple wrapped, static label. Though I've attempted to account for and test every TextView setting I could think of that might affect this – e.g., compound drawables, paddings, selectable text, scrolling, text direction and alignment, etc. – I can't guarantee that I've thought of everything.
I have created an app that actually uses flood fill algorithm to fill colors in bitmaps. I have created some bitmaps (200x200) but I don't know the exact size of bitmap that I should create, I want bitmaps to cover full screen and when I scale bitmaps, they become blur and flood fill doesn't work on them. I saw an app that used GridView to show images and click on image started new activity with image covering full screen. How can I achieve this. Attached is CustomImage that I've use to show bitmap. Any help will be appreciated.
EDITED: I know that GridView doesn't scale up image to full screen, it use another image. That app behaves same for different screen size, those image fill screen of any size without effecting the quality.
public class CustomImage extends View {
public CustomImage(Context context) {
super(context);
} // end constructor
public CustomImage(Context context, int resource_id) {
super(context);
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
mPoint = new Point();
mProgressIndicator = (ProgressIndicator) context;
mBitmap = BitmapFactory.decodeResource(getResources(), resource_id)
.copy(Bitmap.Config.ARGB_8888, true);
} // end constructor
#Override
protected void onDraw(Canvas canvas) {
// draw image
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
} // end onDraw
#Override
public boolean onTouchEvent(MotionEvent event) {
int bWidth = mBitmap.getWidth();
int bHeight = mBitmap.getHeight();
mPoint.x = (int) event.getX();
mPoint.y = (int) event.getY();
mPoint.x = (mPoint.x > bWidth) ? (bWidth - 5) : mPoint.x;
mPoint.y = (mPoint.y > bHeight) ? (bHeight - 5) : mPoint.y;
switch (event.getAction()) {
// called when screen clicked i.e New touch started
case MotionEvent.ACTION_DOWN:
mProgressIndicator.updateProgress(0);
new Filler(mBitmap, mPoint, mPaint.getColor(), mBitmap.getPixel(
mPoint.x, mPoint.y), this).execute();
invalidate();
} // end Case
return true;
} // end onTouchEvent
public void setColor(int color) {
mPaint.setColor(color);
} // end setColor
} // end Class
The GridView you have seen might be using two versions of the same image. One as a big image and another as a scaled down thumbnail image for the grid.
As is, 100 pink circles (same bitmap) appear scattered randomly over the phone screen (as is supposed to). When I tap one of the circles, that circle should disappear (change to the background color). I think I have a fundamental misunderstanding of Android and View in general.I think I have a couple obvious errors (that are not so obvious to me, but I've been staring at it so long that I figured I needed some help). Currently, the screen shows the random circles but nothing more. Touching the screen does nothing. Any better ideas to make the circles disappear? It recently reorganized all the bitmaps when you touched it, but I did something recently, and it stopped. The bitmap is 30px by 30px.
public class DrawV extends View {
private Bitmap bit_dot;
private int width;
private int height;
public int[] width_array = new int[100];
public int[] height_array = new int[100];
private View dotV = (View)findViewById(R.id.bigdocpic);//bitmap
Random rand = new Random();
public DrawV(Context context) {
super(context);
bit_dot = BitmapFactory.decodeResource(getResources(), R.drawable.dot_catch);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
width = metrics.widthPixels;
height = metrics.heightPixels;
}
#Override
//draws 100 randomly placed similar bitmaps
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int height_dimension;
int width_dimension;
for (int i = 0; i < 100; i++){
height_dimension = rand.nextInt(height) + 1;
width_dimension = rand.nextInt(width) + 1;
canvas.drawBitmap(bit_dot, width_dimension, height_dimension, null);
width_array[i] = width_dimension;//
height_array[i] = height_dimension;//
}
}
#Override
public boolean onTouchEvent(MotionEvent event){
Paint p = new Paint();
p.setColor(Color.WHITE);
Path path = new Path();
Canvas c = new Canvas();
for (int i = 0; i < 100; i++){
if ((event.getX() == width_array[i]) && (event.getY() == height_array[i]))
c.drawCircle(width_array[i], height_array[i], 15, p);
}
invalidate();
return false;//false or true?
}
//set visibility of bitmap to invisible
public boolean onTouch(View v, MotionEvent event) {
dotV.setVisibility(View.INVISIBLE);
invalidate();
return false;//false or true? not understanding
}}
Help?
Your onTouchEvent isn't really doing anything important as-is, and you don't have the concept of a circle object.
onDraw should really be drawing these circles from an array/list created earlier - say a List<MyCircles> or MyCircles[]. On touch, you could iterate through all of your circles until you find one that is closest, remove that circle from the array or list, then invalidate.
The reason nothing is happening at all is even though you're drawing those circles again in onTouchEvent, you're redrawing everything yet again in onDraw (invalidate() calls draw/onDraw).
Ideally, create your list of circles in your initializer, draw them in onDraw, and update them in onTouch (That is, delete). There may be a simpler way to do this but this is, at the very least, a more proper approach.
I have an image e.g. the image shown below:
This image has two parts part 1 of size width W and height L and part 2 (smaller part) of width w and height h (call part one as source and part 2 as destination). Let the coordinates of the 1st rectangle be (measured from top left corner): top:100 left: 10 right: 200 bottom: 300 and the coordinates of the 2nd rectangle be (as measured from top left corner): top 50 left: 500 bottom: 100 right: 700
I want to animate from source to destination such that the image translates and zooms in from source to destination.
So my first screen would look like:
and my second image would look like:
How do I tween between these two ?
My code (without animation) looks like as follows:
public class SuperGame extends View implements OnGestureListener
{
int sreenHeight, screenWidth;
int drawCount = 0;
Bitmap bg;
public SuperGame(Context context, Bitmap bmp)
{
this.screenWidth = getContext().getResources().getDisplayMetrics().widthPixels;
this.screenHeight = getContext().getResources().getDisplayMetrics().heightPixels;
bg = BitmapFactory.decodeResource(getResources(),R.drawable.bg_img);
}
#Override
/* this function triggers the image change
*/
public boolean onDown(MotionEvent e) {
invalidate(0,0,screenWidth, screenHeight);
return true;
}
#Override
public void onDraw(Canvas canvas)
{
Rect dest = new Rect(0,0,screenWidth, screenHeight);
if (count==0) //draw the first image part
{
count=1;
Rect src = new Rect(100,10,200,300);//coordinates of rectangle 1
canvas.drawBitmap(bg, src, dest, new Paint());
}
else //draw the second image part - (I'd like to show movement/ transition between these)
{
Rect src = new Rect(50,500,100,700);//coordinates of rectangle 2
count=0;
canvas.drawBitmap(bg, src, dest, new Paint());
}
}
}
How to I animate the transition (which involves zoomin as well as translation)?
You might need to create a custom valueAnimator of type Rect/RectF.
Code example given below:
public class RectFEvaluator
implements TypeEvaluator<RectF>
{
#Override
public RectF evaluate(float fraction, RectF srcRect, RectF destRect) {
RectF betweenRect = new RectF();
betweenRect.bottom = srcRect.bottom + fraction*(destRect.bottom-srcRect.bottom);
betweenRect.top = srcRect.top + fraction*(destRect.top-srcRect.top);
betweenRect.left = srcRect.left + fraction*(destRect.left-srcRect.left);
betweenRect.right = srcRect.right + fraction*(destRect.right-srcRect.right);
return betweenRect;
}
}
The value animator will give you the intermediate values between src Rect and dest Rect.
Once you have these values, updated them using an animation
I have read the android spill on this method tons of times and it isn't ringing any bells. Bellow is a part of my code:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
boolean CollisionTest;
Rect jSquare = new Rect();
Rect mSquare = new Rect();
jSquare.set(0,500,600,400);
mSquare.set(0, 500,700, 100);
canvas.drawRect(mSquare, Some Color..);
canvas.drawRect(jSquare, Some Color...);
CollisionTest = Rect.intersects(jSquare, mSquare);
if (ColisionTest==true){
canvas.drawColor(Color.RED);
}
From the documentation for set
public void set (int left, int top, int right, int bottom)
Set the rectangle's coordinates to the specified values. Note: no range checking is performed, so it is up to the caller to ensure that left <= right and top <= bottom.
500 > 100