Custom view pager with Gradient Background - android

How can we create a custom gradient background view pager like timely app.
I am able to create radial gradient like below
in my tab fragment xml
<view
android:id="#+id/myView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
class="com.android.MyView" />
MyView.java
public class MyView extends View {
Paint BackPaint = new Paint();
Context MyContext;
public MyView(Context context) {
super(context);
init(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context ctx) {
MyContext = ctx;
BackPaint.setStyle(Paint.Style.FILL);
BackPaint.setColor(Color.BLACK);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(w, h);
}
#Override
protected void onDraw(Canvas canvas) {
float w, h, cx, cy, radius;
w = getWidth();
h = getHeight();
cx = w / 2;
cy = h / 2;
if (w > h) {
radius = h / 4;
} else {
radius = w / 4;
}
canvas.drawRect(0, 0, w, h, BackPaint);
Paint MyPaint = new Paint();
MyPaint.setStyle(Paint.Style.FILL);
SharedPreferences prefs;
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
float shaderCx = 0;
float shaderCy = 0;
float shaderRadius = w;
int shaderColor0 = Color.WHITE;
int shaderColor1 = Color.BLACK;
shaderColor0 = prefs.getInt("pref1", 0);
shaderColor1 = prefs.getInt("pref2", 0);
MyPaint.setAntiAlias(true);
Shader radialGradientShader;
radialGradientShader = new RadialGradient(shaderCx, shaderCy,
shaderRadius, shaderColor0, shaderColor1,
Shader.TileMode.MIRROR);
MyPaint.setShader(radialGradientShader);
canvas.drawRect(0, 0, w, h, MyPaint);
// canvas.drawRect(0, 0, w, h, MyPaint);
// canvas.drawCircle(cx, cy, radius, MyPaint);
};
}
but how can we create separate gradient for each tab?

Related

How to know about bitmap getPixel(x,y) from given color code

I know that we can get color from bitmap.getPixel(x,y) method but I do not have x,y and I want to get x,y from given color code.
When onDraw Method will call at the first time I want to draw the line on vertical picker with default color but that time I do not have x,y so not able to call getPixel(x,y) because user-interaction does not happen.
public class VerticalSlideColorPicker extends View {
private String TAG = VerticalSlideColorPicker.class.getName();
private Paint paint;
private Paint strokePaint;
private Path path;
private Bitmap bitmap;
private int viewWidth;
private int viewHeight;
private int centerX;
private float colorPickerRadius;
private OnColorChangeListener onColorChangeListener;
private RectF colorPickerBody;
private float selectorYPos;
private int borderColor;
private float borderWidth;
private int[] colors;
private boolean cacheBitmap = true;
private Context mContext;
public VerticalSlideColorPicker(Context context) {
super(context);
mContext = context;
init();
}
public VerticalSlideColorPicker(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.VerticalSlideColorPicker,
0, 0);
try {
borderColor = a.getColor(R.styleable.VerticalSlideColorPicker_borderColor, Color.WHITE);
borderWidth = a.getDimension(R.styleable.VerticalSlideColorPicker_borderWidth, 10f);
int colorsResourceId = a.getResourceId(R.styleable.VerticalSlideColorPicker_colors, R.array.default_colors);
colors = a.getResources().getIntArray(colorsResourceId);
}
finally {
a.recycle();
}
init();
}
public VerticalSlideColorPicker(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public VerticalSlideColorPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
setWillNotDraw(false);
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
path = new Path();
strokePaint = new Paint();
strokePaint.setStyle(Paint.Style.STROKE);
strokePaint.setColor(borderColor);
strokePaint.setAntiAlias(true);
strokePaint.setStrokeWidth(borderWidth);
setDrawingCacheEnabled(true);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path.addRect(colorPickerBody, Path.Direction.CW);
path.addRect(colorPickerBody, Path.Direction.CW);
canvas.drawPath(path, strokePaint);
canvas.drawPath(path, paint);
if (cacheBitmap) {
bitmap = getDrawingCache();
cacheBitmap = false;
setColor(ContextCompat.getColor(getContext(), R.color.tag_layout_border_audioyes_darkblue));
//invalidate();
}
else {
canvas.drawLine(colorPickerBody.left, selectorYPos, colorPickerBody.right, selectorYPos, strokePaint);
}
}
/**
* Set the color this view should show.
*
* #param color The color that should be selected. #argb
*/
public void setColor(int color) {
/*int[] pixels = new int[bitmap.getHeight()*bitmap.getWidth()];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
for (int i=0; i<bitmap.getWidth()*5; i++)
pixels[i] = ContextCompat.getColor(getContext(), R.color.blue_picker);
bitmap.setPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());*/
/* int alpha = Color.alpha(color);
int red = Color.red(color);
int blue = Color.blue(color);
int green = Color.green(color);
float[] hsv = new float[3];
Color.RGBToHSV(red, green, blue, hsv);*/
/* selectorYPos = 584;
int selectedColor = bitmap.getPixel(viewWidth / 2, (int) selectorYPos);*/
/* this.alpha = alpha;
hue = hsv[0];
sat = hsv[1];
val = hsv[2];*/
if (onColorChangeListener != null) {
onColorChangeListener.onColorChange(color);
}
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float yPos = Math.min(event.getY(), colorPickerBody.bottom);
android.util.Log.e(TAG, "Float :" + yPos);
yPos = Math.max(colorPickerBody.top, yPos);
android.util.Log.e(TAG, "Normal :" + yPos);
selectorYPos = yPos;
int selectedColor = bitmap.getPixel(viewWidth / 2, (int) selectorYPos);
android.util.Log.e(TAG, "Color :" + selectedColor);
if (onColorChangeListener != null) {
onColorChangeListener.onColorChange(selectedColor);
}
invalidate();
return true;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
centerX = viewWidth / 2;
colorPickerRadius = (viewWidth / 2) - borderWidth;
colorPickerBody = new RectF(centerX - colorPickerRadius, borderWidth + colorPickerRadius, centerX + colorPickerRadius, viewHeight - (borderWidth + colorPickerRadius));
LinearGradient gradient = new LinearGradient(colorPickerBody.left, colorPickerBody.top,
colorPickerBody.right,
colorPickerBody.bottom, colors, null, Shader.TileMode.CLAMP);
paint.setShader(gradient);
resetToDefault();
}
public void setBorderColor(int borderColor) {
this.borderColor = borderColor;
invalidate();
}
public void setBorderWidth(float borderWidth) {
this.borderWidth = borderWidth;
invalidate();
}
public void setColors(int[] colors) {
this.colors = colors;
cacheBitmap = true;
invalidate();
}
public void resetToDefault() {
selectorYPos = borderWidth + colorPickerRadius;
if (onColorChangeListener != null) {
onColorChangeListener.onColorChange(Color.TRANSPARENT);
}
invalidate();
}
public void setOnColorChangeListener(OnColorChangeListener onColorChangeListener) {
this.onColorChangeListener = onColorChangeListener;
}
}
A brute force solution could be the following:
private List<Point> getPixelswithColor(Bitmap bitmap, int colorId) {
List<Point> pixels = new ArrayList();
for (int x = 0; x < bitmap.getWidth(); x++) {
for (int y = 0; y < bitmap.getHeight(); y++) {
if (bitmap.getPixel(x, y) == colorId) {
pixels.add(new Point(x, y));
}
}
}
return pixels;
}

Android Create a circle hole in a centerCropped image

I come again for an android brain idea!
I would like to put a circle hole hole in a imageView which bitmap is scaled as centerCrop. I know where I need to put the circle hole( in dp from left and bottom) and the hole radius. But don't know how to build it!
I know that I can use Porterduff to do the hole but what you suggest to do?
Custom bitmap
Custom drawable/view
Custom code
Thanks
Following Answers there is my CustomImage with hole:
public class MyImageView extends ImageView {
private AttributeSet attrs;
private float y;
private float x;
private float r;
private Paint paint;
private Rect mSrcRect;
private Rect mDestRect;
private Bitmap mBitmap;
private int alreadycalled = 0;
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.attrs = attrs;
initView();
}
public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.attrs = attrs;
initView();
}
public MyImageView(Context context, float x, float y, float radius) {
super(context);
this.x = x;
this.y = y;
this.r = radius;
Log.d("parameters", String.format("left:%s , right:%s, radius:%s", String.valueOf(x), String.valueOf(y), String.valueOf(r)));
initView();
}
private void initView() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(10);
paint.setColor(0xff000000);
}
#Override
protected void onDraw(Canvas canvas) {
alreadycalled++;
Log.d("alreadycalled", "called " + alreadycalled);
Drawable mDrawable = getDrawable();
if (mDrawable == null) {
return; // couldn't resolve the URI
}
int dWidth = mDrawable.getIntrinsicWidth();
int dHeight = mDrawable.getIntrinsicHeight();
float scale = 1.0f;
scale = Math.max(getWidth() * 1.0f / dWidth, getHeight()
* 1.0f / dHeight);
int nWidth = (int) (dWidth * scale);
int nHeight = (int) (dHeight * scale);
int offsetLeft = (nWidth - getWidth()) / 2;
int offsetTop = (nHeight - getHeight()) / 2;
mBitmap = ((BitmapDrawable) mDrawable).getBitmap();
//custom mSrcRect mDestRect to achieve centerCrop
mSrcRect = new Rect(0, 0, dWidth, dWidth);
mDestRect = new Rect(-offsetLeft, -offsetTop, getWidth() + offsetLeft, getHeight() + offsetTop);
Log.d("src", mSrcRect.toString());
Log.d("dest", mDestRect.toString());
int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), null,
Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
| Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
| Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG);
paint.setColor(0xffffffff);
canvas.drawBitmap(mBitmap, mSrcRect, mDestRect, paint);
paint.setColor(0xffff0000);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
Log.d("position", String.format("%s , %s", String.valueOf(x), String.valueOf(y)));
canvas.drawCircle(x, y, r, paint);
paint.setXfermode(null);
canvas.restoreToCount(sc);
}
I called it programmatically with theses lines :
BitmapDrawable bd=(BitmapDrawable) getResources().getDrawable(R.drawable.triangle_bas_accueil2);
MyImageView customImView = new MyImageView(getApplicationContext(), mX, mY, mRadius);
customImView.setImageDrawable(bd);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.BOTTOM;
customImView.setLayoutParams(params);
down_relative.addView(customImView);
But the onDraw() method is called twice (maybe it needs) but that makes me two holes, one that I can change parameters but the other still at the same place ! The container of the MyImageView is a RelativeLayout.
If someOne has an idea?
#tiny-sunlight ?
This one is just for CenterCrop and can't deal with scaleType.And this code may have some problems because I'm not good at canvas.
public class MyImageView extends ImageView {
private final AttributeSet attrs;
private Paint paint;
private Rect mSrcRect;
private Rect mDestRect;
private Bitmap mBitmap;
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.attrs = attrs;
initView();
}
public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.attrs = attrs;
initView();
}
private void initView() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeWidth(10);
paint.setColor(0xff000000);
}
#Override
protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
//create the drawable.Maybe you can cache it.
Drawable mDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.triangle_bas_accueil2);
if (mDrawable == null) {
return; // couldn't resolve the URI
}
int dWidth = mDrawable.getIntrinsicWidth();
int dHeight = mDrawable.getIntrinsicHeight();
float scale = 1.0f;
scale = Math.max(getWidth() * 1.0f / dWidth, getHeight()
* 1.0f / dHeight);
int nWidth = (int) (dWidth*scale);
int nHeight = (int) (dHeight*scale);
int offsetLeft = (nWidth - getWidth())/2;
int offsetTop = (nHeight - getHeight())/2;
//cache mBitmap
mBitmap = mBitmap == null ? ((BitmapDrawable) mDrawable).getBitmap(): mBitmap;
//custom mSrcRect mDestRect to achieve centerCrop
mSrcRect = new Rect(0, 0, dWidth, dWidth);
mDestRect = new Rect(-offsetLeft, -offsetTop,getWidth()+offsetLeft, getHeight()+offsetTop);
int x = 250;int r = 100;
int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), null,
Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
| Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
| Canvas.FULL_COLOR_LAYER_SAVE_FLAG
| Canvas.CLIP_TO_LAYER_SAVE_FLAG);
paint.setColor(0xffffffff);
canvas.drawBitmap(mBitmap,mSrcRect,mDestRect,paint);
paint.setColor(0xff000000);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
canvas.drawCircle(x,x,r,paint);
paint.setXfermode(null);
canvas.restoreToCount(sc);
}
}
Custom code. Loop through each pixel and change the alpha. Here is some pseudocode:
for (int y = 0; y < imageHeight; y++) {
for (int x = 0; x < imageWidth; x++) {
// Check if the current pixel is within the circle
if (dist(x, y, centerX, centerY) <= radius) {
// Change the alpha
image.setPixelAlpha(x, y, 0);
}
}
}

Display a grid using Canvas in Android

I'm trying to display a grid in my Android application. I'm using the "onDraw" method of a custom view I created for this purpose.
The problem is that the result is very strange, not all lines are drawn and some artifacts are visible. May I have your help to solve this?
Here's the code I use:
public class GridView extends View {
private int cellHeight;
private int cellWidth;
private int cellRows = 16;
private int cellColumns = 16;
private Paint lines = new Paint();
public GridView(Context context) {
super(context);
init();
}
public GridView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public GridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
lines.setStyle(Paint.Style.FILL_AND_STROKE);
lines.setColor(Color.BLACK);
cellWidth = getWidth() / cellColumns;
cellHeight = getHeight() / cellRows;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
cellWidth = getWidth() / cellColumns;
cellHeight = getHeight() / cellRows;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
for (int i = 0; i < cellRows; i++)
{
canvas.drawLine(0, i * cellHeight, getWidth(), i * cellHeight,
lines);
}
for (int i = 0; i < cellColumns; i++)
{
canvas.drawLine(i * cellWidth, 0, i * cellWidth, getHeight(),
lines);
}
}
}
This is what I get in EMULATOR:
http://hpics.li/ca14cd1
Moreover, in Android preview (when designing activity), I can see the result expected:
http://hpics.li/7b97afb
The problem occurs when the application is really started.

How to display Text in Android Canvas ShapeDrawable with in the RectShape or OvalShape?

I'm trying to display Text in RectShape which uses ShapeDrawable to display in Canvas.
I'm able to display RectShape in this code, but looking for how to display the String on that!
public class CustomDrawableView extends View {
private ShapeDrawable mDrawable;
public CustomDrawableView(Context context) {
super(context);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
or
public class ShapeDrawableTest extends View {
ShapeDrawable shapes = new ShapeDrawable();
public ShapeDrawableTest(Context context) {
super(context);
}
public ShapeDrawableTest(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
shapes.draw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX(); // Use getX(int) for multi-finger
// gestures
int y = (int) event.getY();
makeShapeDrawable(x, y);
invalidate();
return (true); // Handled touch event
} else {
return (false); // Did not handle touch event
}
}
private void makeShapeDrawable(int x, int y) {
int maxWidth = getWidth() / 10;
int maxHeight = getHeight() / 10;
Shape shape;
shape = new RectShape();
shapes = new ShapeDrawable(shape);
int width = RandomUtils.randomInt(maxWidth) + 5;
int height = RandomUtils.randomInt(maxHeight) + 5;
shapes.setBounds(x - width / 2, y - height / 2, x + width / 2, y
+ height / 2);
shapes.getPaint().setColor(Color.BLUE);
}
}
What I tried is:
public class CustomDrawableView extends View {
public ShapeDrawable mDrawable;
public CustomDrawableView(Context context) {
super(context);
}
public CustomDrawableView(Context context, AttributeSet attrs) {
super(context, attrs);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
//mDrawable.getPaint().setColor(0xff74AC23);
final String s = "Hello";
Paint p = new Paint();
Rect bounds = new Rect();
bounds.set(x, y, x + width, y + height);
p.setTextSize(20);
p.setColor(Color.YELLOW);
p.getTextBounds(s, 0, s.length(), bounds);
mDrawable.getPaint().getTextBounds(s, 0, s.length(), bounds);
mDrawable.setBounds(x, y, x + width, y + height);
}
// public CustomDrawableView(Context context, AttributeSet attrs, int defStyle) {
// super(context, attrs, defStyle);
//
// }
public void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
Screenshot:
The best option for me is to create a custom TextDrawable that handles properly how to display a piece of text. Then in your CustomDrawableView in your onDraw(Canvas c) method you can call it to display the text and the oval.
Take a look at this answer I wrote recently as it contains how to do it properly.

Draw a transparent circle onto a filled android canvas

I am trying to do something very simple (see above). I want all of the pixels of a canvas to be a solid color, except for the the pixels that fill a centered circle. I have read hundreds stack overflow post on this subject and have tried hundreds of things including setting the PorterDuff.Mode. Here is my current onDraw() of MyView extends View:
protected void onDraw(Canvas canvas) {
int w = canvas.getWidth();
int h = canvas.getHeight();
Paint framePaint = new Paint();
framePaint.setStyle(Paint.Style.FILL);
framePaint.setColor(Color.BLUE);
canvas.drawRect(0, 0, w, h, framePaint);
Paint transparentPaint = new Paint();
transparentPaint.setColor(Color.TRANSPARENT);
transparentPaint.setAntiAlias(true);
canvas.drawCircle(w / 2, h / 2, (w + h) / 4, transparentPaint);
}
Am I misunderstanding something, why cant I paint over an existing pixel with transparent paint. When I do this the pixel stays the same. When I use PorterDuff, the pixel turns black. Please help.
Try this:
public class TransparentCircle extends View {
Bitmap bm;
Canvas cv;
Paint eraser;
public TransparentCircle(Context context) {
super(context);
Init();
}
public TransparentCircle(Context context, AttributeSet attrs) {
super(context, attrs);
Init();
}
public TransparentCircle(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
Init();
}
private void Init(){
eraser = new Paint();
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
eraser.setAntiAlias(true);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
cv = new Canvas(bm);
}
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
int w = getWidth();
int h = getHeight();
int radius = w > h ? h / 2 : w / 2;
bm.eraseColor(Color.TRANSPARENT);
cv.drawColor(Color.BLUE);
cv.drawCircle(w / 2, h / 2, radius, eraser);
canvas.drawBitmap(bm, 0, 0, null);
super.onDraw(canvas);
}
}

Categories

Resources