Highlight/select a region in a bitmap - android

I am trying to be able to select/highlight a specific grid position onTouch.
Basically, I have an image, with a canvas/bitmap over layering the top of the image, I want to be able to click on a point of the image, and have that box become highlighted(first step is highlighting the grid, I will perform other algorithms on this later on)..
Here is the code for what I have now.. I am able to grab the x y coordinates, but I do not know how to associate the x y coordinates with the grid position.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.MeasureSpec;
public class ImageWithGridView extends View {
private int rows = 12;
private int columns = 12;
private float width;
private float height;
public static final String TAG="ImageWithGridView";
private static final String SELX = "selX";
private static final String SELY = "selY";
private static final String VIEW_STATE = "viewState";
//private static final int ID = 92;
private int selX; //X index of selection
private int selY; //Y index of selection
private final Bitmap bitmap;
public ImageWithGridView(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample);
//use your own image file name, instead of mobot_spring
}
public ImageWithGridView(Context context, AttributeSet attrs){
super(context, attrs);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample);
//TODO Auto-generated constructor sub
}
public ImageWithGridView(Context context, AttributeSet attrs, int defStyle) {
super (context, attrs, defStyle);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample);
//TODO Auto-generated constructor stub
}
#Override
protected Parcelable onSaveInstanceState() {
Parcelable p = super.onSaveInstanceState();
Log.d(TAG, "onSaveInstanceState");
Bundle bundle = new Bundle();
bundle.putInt(SELX, selY);
bundle.putInt(SELY, selY);
bundle.putParcelable(VIEW_STATE, p);
return bundle;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
Log.d(TAG, "onRestoreInstanceState");
Bundle bundle = (Bundle) state;
selX = bundle.getInt(SELX);
selY = bundle.getInt(SELY);
super.onRestoreInstanceState(bundle.getParcelable(VIEW_STATE));
return;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
//adjust the ratio for width and height here:
this.setMeasuredDimension(parentWidth, parentHeight*2/3);
}
#Override
protected void onSizeChanged(int newWidth, int newHeight, int oldw, int oldh) {
width = newWidth / (float) columns;
height = newHeight / (float)rows;
Log.d(TAG, "~~~~~~~~~~~onSizeChanged: width " + width + ", height " + height);
super.onSizeChanged(newWidth, newWidth, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
RectF dst = new RectF(width, height, (columns-1) * width, (rows - 1) * height);
//Draw the background...
Paint background = new Paint();
background.setColor(getResources().getColor(R.color.background));
Log.d(TAG, "~~~~~~~~~10 ");
canvas.drawRect(0, 0, getWidth(), getHeight(), background);
Log.d(TAG, "~~~~~~~~~20 ");
canvas.drawBitmap(bitmap, null, dst, null);
Log.d(TAG, "~~~~~~~~~30 ");
//Define colors for the grid lines
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.dark));
Paint hilite = new Paint();
hilite.setColor(getResources().getColor(R.color.hilite));
Paint light = new Paint();
light.setColor(getResources().getColor(R.color.light));
//Draw the minor grid lines
for (int i = 0; i < rows; i++) {
canvas.drawLine(0, i * height-1, getWidth(), i * height-1, dark);
canvas.drawLine(0, i * height, getWidth(), i * height, light);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1, hilite);
}
for (int i=0; i<columns; i++) {
canvas.drawLine(i * width-1, 0, i* width-1, getHeight(), dark);
canvas.drawLine(i * width, 0, i * width, getHeight(), light);
canvas.drawLine(i * width + 1, 0, i* width + 1, getHeight(), hilite);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN){
return super.onTouchEvent(event);
}
selX = (int) event.getX();
selY = (int) event.getY();
Log.d(TAG, "onTouchEvent: x " + selX + ", y " + selY);
return true;
}
public int getClickedX() {return selX;}
public int getClickedY() {return selY;}
}
This is my other class
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class CustomizeImageViewActivity extends Activity{
/** Called when the activity is first created. */
private Button btnShow;
private TextView label;
private ImageWithGridView imgView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//setContentView(R.layout.relative_layout);
//setContentView(R.layout.table_layout);
btnShow = (Button) findViewById(R.id.btnShow);
label = (TextView) findViewById(R.id.label);
imgView = (ImageWithGridView)findViewById(R.id.imageView1);
btnShow.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View arg0) {
label.setText("("+imgView.getClickedX() + "," + imgView.getClickedY() + ")");
}
});
}
}
Please advise with any guides/tutorials I should look at.. I have tried doing some research but I have not been able to find anything on this.

Related

Custom Android View displaying differently in Linear and Relative Layouts

I've created a custom view (ArrowContainer) to wrap around other elements giving them an arrow shaped background. However, my view displays differently when contained in a Relative Layout to how it displays when contained in a Linear Layout.
Here is the problem, the top ArrowContainer is contained in a LinearLayout and behaves correctly, the bottom ArrowContainer is contained in a RelativeLayout and behaves incorrectly.
Has anyone seen something like this before? The debug code I have inserted in ArrowContainer.java suggests that the problem arises from RelativeLayout measuring the view twice, but I'm not sure why this causes a problem...
Below is the code:
ArrowContainer.java
package com.example.arrowcontainertest;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
public class ArrowContainer extends ViewGroup {
private static final int ARROW_LEFT = 0;
private static final int ARROW_RIGHT = 1;
private static final int ARROW_BOTH = 2;
private static final int DEFAULT_COLOUR = 0xFFFF0000;
private static final int HORIZONTAL_PADDING = 150;
private Path path;
private Paint paint;
private int arrowSide = ARROW_RIGHT;
private int colour = DEFAULT_COLOUR;
private int downColour;
private Paint downPaint;
private Boolean isButton = false;
private View child;
public ArrowContainer(Context context) {
super(context);
init();
}
public ArrowContainer(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArrowContainer, 0, 0);
try {
arrowSide = a.getInteger(R.styleable.ArrowContainer_arrowSide, ARROW_RIGHT);
colour = a.getColor(R.styleable.ArrowContainer_colour, DEFAULT_COLOUR);
isButton = a.getBoolean(R.styleable.ArrowContainer_isButton, false);
} finally {
a.recycle();
}
init();
}
public ArrowContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArrowContainer, 0, 0);
try {
arrowSide = a.getInteger(R.styleable.ArrowContainer_arrowSide, ARROW_RIGHT);
colour = a.getColor(R.styleable.ArrowContainer_colour, DEFAULT_COLOUR);
isButton = a.getBoolean(R.styleable.ArrowContainer_isButton, false);
} finally {
a.recycle();
}
init();
}
private void init() {
paint = new Paint();
paint.setColor(colour);
paint.setStyle(Style.FILL);
setWillNotDraw(false);
if (isButton) {
setFocusable(true);
setClickable(true);
downColour = 0xFF00FF00;
downPaint = new Paint();
downPaint.setColor(downColour);
downPaint.setStyle(Style.FILL);
}
}
#Override
protected void onFinishInflate() {
// Must have exactly 1 child
assert getChildCount()==1;
if (getChildCount() == 1) {
child = getChildAt(0);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Debug
Log.e("DEBUG", "Type:" + getParent().getClass());
Log.e("DEBUG", "Width Mode: " + MeasureSpec.getMode(widthMeasureSpec));
Log.e("DEBUG", "Height Mode: " + MeasureSpec.getMode(heightMeasureSpec));
Log.e("DEBUG", "Width Size: " + MeasureSpec.getSize(widthMeasureSpec));
Log.e("DEBUG", "Height Size: " + MeasureSpec.getSize(heightMeasureSpec));
// Restrict the childs width to at most this components size minus a fixed value (HORIZONTAL_PADDING*numArrows)
int numArrows=0;
switch (arrowSide) {
case ARROW_RIGHT:
numArrows = 1;
break;
case ARROW_LEFT:
numArrows = 1;
break;
case ARROW_BOTH:
numArrows = 2;
break;
}
int widthSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec)-HORIZONTAL_PADDING*numArrows, MeasureSpec.AT_MOST);
int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
child.measure(widthSpec, heightSpec);
int width = child.getMeasuredWidth();
int height = child.getMeasuredHeight();
setMeasuredDimension(width + (int) (numArrows*height/2f), height);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
switch (arrowSide) {
case ARROW_RIGHT:
// Hug left
child.layout(0, height/2 - childHeight/2, width - height/2, height/2 + childHeight/2);
break;
case ARROW_LEFT:
// Hug right
child.layout(height/2, height/2 - childHeight/2, width, height/2 + childHeight/2);
break;
case ARROW_BOTH:
// Center
child.layout(width/2 - childWidth/2, height/2 - childHeight/2, width/2 + childWidth/2, height/2 + childHeight/2);
break;
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
path = new Path();
switch (arrowSide) {
case ARROW_RIGHT:
path.lineTo(0, h);
path.lineTo(w-h/2f, h);
path.lineTo(w, h/2f);
path.lineTo(w-h/2f, 0);
break;
case ARROW_LEFT:
path.moveTo(h/2f, 0);
path.lineTo(0, h/2f);
path.lineTo(h/2f, h);
path.lineTo(w, h);
path.lineTo(w, 0);
break;
case ARROW_BOTH:
path.moveTo(h/2f, 0);
path.lineTo(0, h/2f);
path.lineTo(h/2f, h);
path.lineTo(w-h/2f, h);
path.lineTo(w, h/2f);
path.lineTo(w-h/2f, 0);
break;
}
path.close();
}
#Override
protected void onDraw(Canvas canvas) {
invalidate();
if (isPressed()) {
canvas.drawPath(path, downPaint);
} else {
canvas.drawPath(path, paint);
}
super.onDraw(canvas);
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" xmlns:app="http://schemas.android.com/apk/res/com.example.arrowcontainertest">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.arrowcontainertest.ArrowContainer
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:arrowSide="right">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Play"
android:textSize="50sp"/>
</com.example.arrowcontainertest.ArrowContainer>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.arrowcontainertest.ArrowContainer
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:arrowSide="right">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Play"
android:textSize="50sp"/>
</com.example.arrowcontainertest.ArrowContainer>
</RelativeLayout>
MainActivity.java
package com.example.arrowcontainertest;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
An update:
I've been unable to solve this problem and this component has been causing problems in other situations. As such I decided to rewrite the component to use a little custom functionality as possible.
My solution has been to create a custom LinearLayout which contains a nested LinearLayout. The outer layout is responsible for drawing the background, and applies sufficient padding to allow space to draw the arrows. All children get passed to the inner layout. This solution isn't perfect as there is often excess padding and so wasted space, but it is sufficient for my purposes.
Code is here:
package com.example.arrowcontainertest;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
public class NewArrowContainer extends LinearLayout {
private static final int ARROW_LEFT = 0;
private static final int ARROW_RIGHT = 1;
private static final int ARROW_BOTH = 2;
private static final int DEFAULT_COLOUR = 0xFFFF0000;
private static final int ARROW_MAX_WIDTH = 150;
private LinearLayout childLayout;
private Path path;
private Paint paint;
private int arrowSide = ARROW_RIGHT;
private int colour = DEFAULT_COLOUR;
private int downColour;
private Paint downPaint;
private Boolean isButton = false;
public NewArrowContainer(Context context) {
super(context);
init();
}
public NewArrowContainer(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArrowContainer, 0, 0);
try {
arrowSide = a.getInteger(R.styleable.ArrowContainer_arrowSide, ARROW_RIGHT);
colour = a.getColor(R.styleable.ArrowContainer_colour, DEFAULT_COLOUR);
isButton = a.getBoolean(R.styleable.ArrowContainer_isButton, false);
} finally {
a.recycle();
}
init();
}
public NewArrowContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArrowContainer, 0, 0);
try {
arrowSide = a.getInteger(R.styleable.ArrowContainer_arrowSide, ARROW_RIGHT);
colour = a.getColor(R.styleable.ArrowContainer_colour, DEFAULT_COLOUR);
isButton = a.getBoolean(R.styleable.ArrowContainer_isButton, false);
} finally {
a.recycle();
}
init();
}
private void init() {
paint = new Paint();
paint.setColor(colour);
paint.setStyle(Style.FILL);
setWillNotDraw(false);
if (isButton) {
setFocusable(true);
setClickable(true);
downColour = 0xFF00FF00;
downPaint = new Paint();
downPaint.setColor(downColour);
downPaint.setStyle(Style.FILL);
}
LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(R.layout.arrow_container, this);
childLayout = (LinearLayout) findViewById(R.id.child);
// Pass properties to childLayout
childLayout.setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom());
childLayout.setOrientation(getOrientation());
// Give the padding sufficient for arrows
switch (arrowSide) {
case ARROW_RIGHT:
setPadding(0, 0, ARROW_MAX_WIDTH, 0);
break;
case ARROW_LEFT:
setPadding(ARROW_MAX_WIDTH, 0, 0, 0);
break;
case ARROW_BOTH:
setPadding(ARROW_MAX_WIDTH, 0, ARROW_MAX_WIDTH, 0);
break;
}
}
public void setColour(int colour) {
paint.setColor(colour);
}
#Override
public void onFinishInflate() {
// Pass all children to the childLayout
while (getChildCount() > 1) {
View v = getChildAt(1);
removeViewAt(1);
childLayout.addView(v);
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
path = new Path();
switch (arrowSide) {
case ARROW_RIGHT:
path.lineTo(0, h);
path.lineTo(w-ARROW_MAX_WIDTH, h);
path.lineTo(w-ARROW_MAX_WIDTH+h/2f, h/2f);
path.lineTo(w-ARROW_MAX_WIDTH, 0);
break;
case ARROW_LEFT:
path.moveTo(ARROW_MAX_WIDTH-h/2f, h/2f);
path.lineTo(ARROW_MAX_WIDTH, h);
path.lineTo(w, h);
path.lineTo(w, 0);
path.lineTo(ARROW_MAX_WIDTH, 0);
break;
case ARROW_BOTH:
path.moveTo(ARROW_MAX_WIDTH-h/2f, h/2f);
path.lineTo(ARROW_MAX_WIDTH, h);
path.lineTo(w-ARROW_MAX_WIDTH, h);
path.lineTo(w-ARROW_MAX_WIDTH+h/2f, h/2f);
path.lineTo(w-ARROW_MAX_WIDTH, 0);
path.lineTo(ARROW_MAX_WIDTH, 0);
break;
}
path.close();
}
#Override
protected void onDraw(Canvas canvas) {
invalidate();
if (isPressed()) {
canvas.drawPath(path, downPaint);
} else {
canvas.drawPath(path, paint);
}
super.onDraw(canvas);
}
}
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec)-HORIZONTAL_PADDING*numArrows, MeasureSpec.AT_MOST);
I am concerned about this line, why you don't check if width, supplied to makeMeasureSpec, isn't negative? This method doesn't perform range check, so it your responsibility. Negative width = invalid measureSpec = undefined behavior.
Also, when i have implemented some custom layouts, i've used super.onMeasure to determine maximum available dimensions and then used them via getMeasuredWidth(), getMeasuredHeight().

Create Custom Seekbar in android

can any one help me to create balow image cutomize seek bar
i have already go throught
SeekBar with custom thumb and segmented text
and SeekBar Thumb position issue
but i am not success to create my custome seekbar pls help me
Use Library From This Link: This link and put into your project,
Now Create A Seekbar Like This Class:
package com.tokaracamara.android.verticalslidevar;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class DemoSeek extends AbsVerticalSeekBar {
public interface OnSeekBarChangeListener {
void onProgressChanged(DemoSeek seekBar, int progress, boolean fromUser);
void onStartTrackingTouch(DemoSeek seekBar);
void onStopTrackingTouch(DemoSeek seekBar);
}
private OnSeekBarChangeListener mOnSeekBarChangeListener;
private Drawable progressDrawable;
private Rect barBounds, labelTextRect;
private Bitmap labelBackground;
private Point labelPos;
private Paint labelTextPaint, labelBackgroundPaint;
int viewWidth, barHeight, labelOffset;
// private int thumbX;
float progressPosX;
private String expression;
public DemoSeek(Context context) {
super(context);
// Log.i("Seekbar", "DemoSeek");
progressDrawable = getProgressDrawable();
// labelBackground = BitmapFactory.decodeResource(getResources(),
// R.drawable.thumb_marker);
labelBackground = drawableToBitmap(mThumb);
labelTextPaint = new Paint();
labelTextPaint.setColor(Color.WHITE);
labelTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
labelTextPaint.setAntiAlias(true);
labelTextPaint.setDither(true);
labelTextPaint.setTextSize(13f);
labelBackgroundPaint = new Paint();
barBounds = new Rect();
labelTextRect = new Rect();
labelPos = new Point();
}
public Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
#Override
void onProgressRefresh(float scale, boolean fromUser) {
super.onProgressRefresh(scale, fromUser);
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onProgressChanged(this, getProgress(),
fromUser);
}
}
public DemoSeek(Context context, AttributeSet attrs) {
super(context, attrs);
progressDrawable = getProgressDrawable();
labelBackground = BitmapFactory.decodeResource(getResources(),
R.drawable.thumb_with_arrow);
labelTextPaint = new Paint();
labelTextPaint.setColor(Color.WHITE);
labelTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
labelTextPaint.setAntiAlias(true);
labelTextPaint.setDither(true);
labelTextPaint.setTextSize(15f);
labelBackgroundPaint = new Paint();
barBounds = new Rect();
labelTextRect = new Rect();
labelPos = new Point();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Log.i("Seekbar", "onMeasure");
if (labelBackground != null) {
viewWidth = getMeasuredWidth();
barHeight = getMeasuredHeight() - getPaddingTop()
- getPaddingBottom();
setMeasuredDimension(viewWidth + labelBackground.getWidth(),
barHeight + labelBackground.getHeight() / 2);
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.save();
if (labelBackground != null) {
barBounds.left = getPaddingLeft();
barBounds.top = (int) (labelBackground.getHeight() / 2f);
barBounds.right = barBounds.left + viewWidth - getPaddingRight()
- getPaddingLeft();
barBounds.bottom = barBounds.top + barHeight - getPaddingBottom()
- getPaddingTop();
progressPosX = barBounds.top
+ ((float) this.getProgress() / (float) this.getMax())
* barBounds.height() + getTopPaddingOffset();
labelPos.y = getBottom() - (int) progressPosX - labelOffset
+ (int) (getProgress() * 0.1f);
labelPos.x = getPaddingLeft();
progressDrawable = getProgressDrawable();
progressDrawable.setBounds(barBounds.left, barBounds.top,
barBounds.right, getBottom());
progressDrawable.draw(canvas);
String pro = getProgress() * multiplier + "";
if (expression != null) {
pro = pro.concat(expression);
}
labelTextPaint.getTextBounds(pro, 0, pro.length(), labelTextRect);
canvas.drawBitmap(labelBackground, labelPos.x, labelPos.y,
labelBackgroundPaint);
canvas.drawText(pro, labelPos.x + labelBackground.getWidth() / 2
- labelTextRect.width() / 2 + 15, labelPos.y
+ labelBackground.getHeight() / 2 + labelTextRect.height()
/ 2 - 5, labelTextPaint);
}
canvas.restore();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
invalidate();
return super.onTouchEvent(event);
}
public void setOnSeekBarChangeListener(
com.tokaracamara.android.verticalslidevar.DemoSeek.OnSeekBarChangeListener onSeekBarChangeListener) {
mOnSeekBarChangeListener = (OnSeekBarChangeListener) onSeekBarChangeListener;
}
#Override
void onStartTrackingTouch() {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStartTrackingTouch(this);
}
}
#Override
void onStopTrackingTouch() {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStopTrackingTouch(this);
}
}
private int multiplier = 1;
public void setMultiplier(int multiplier) {
this.multiplier = multiplier;
}
public int getMultiplier() {
return multiplier;
}
public void setExpression(String expression) {
this.expression = expression.trim();
}
public String getExpression() {
return expression;
}
}
Create Xml Like This:
<com.tokaracamara.android.verticalslidevar.DemoSeek
android:id="#+id/v_four_university"
android:layout_width="#dimen/vs_width"
android:layout_height="match_parent"
android:clickable="false"
android:focusable="false"
android:longClickable="false"
android:progress="50"
android:progressDrawable="#drawable/progress_vertical"
android:saveEnabled="false"
android:thumb="#drawable/your thumb" />

onDraw not firing when created

My custom view's onDraw() is not being fired. Why? I am using 2.3.3. Shouldn't the view automatically draw when it gets created? The onMeasure() method is being fired and I get the correct screen width and height.
package com.example.assignment2b;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.View;
import android.view.WindowManager;
public class AcesActivity extends Activity {
private static final String TAG = "DEBUG";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
HeartView heartView = new HeartView(this);
setContentView(heartView);
heartView.invalidate();
}
class HeartView extends View {
private int screenWidth;
private int screenHeight;
private Context context;
public HeartView(Context context) {
super(context);
this.context = context;
}
#Override
public void onDraw(Canvas canvas) {
Log.println(Log.DEBUG, TAG, "onDraw fired");
int cardWidth = screenWidth - 10;
int cardHeight = (int) (cardWidth * 1.4);
canvas.drawColor(Color.DKGRAY);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(5, (screenHeight/2) - (cardHeight/2), screenWidth - 5, (screenHeight/2) + (cardHeight/2), paint);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(5, (screenHeight/2) - (cardHeight/2), screenWidth - 5, (screenHeight/2) + (cardHeight/2), paint);
}
#Override
public void onMeasure(int width, int height) {
Log.println(Log.DEBUG, TAG, "onMeasure fired");
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
screenWidth = display.getWidth();
screenHeight = display.getHeight();
setMeasuredDimension(screenWidth, screenHeight);
Log.println(Log.DEBUG, TAG, "screenWidth = " + screenWidth);
Log.println(Log.DEBUG, TAG, "scrrenHeight = " + screenHeight);
super.onMeasure(screenWidth, screenHeight);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
}
A few different issues going on. First as #dragonwrenn suggested, without a ViewGroup and layout params, your view has no intrinsic bounds. The call to invalidate() is unnecessary, but not problematic.
public class AcesActivity extends Activity {
private static final String TAG = "DEBUG";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout rl = new RelativeLayout(this);
RelativeLayout.LayoutParams params = new
RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
setContentView(rl);
HeartView heartView = new HeartView(this);
heartView.setLayoutParams(params);
rl.addView(heartView);
}
class HeartView extends View {
private int screenWidth;
private int screenHeight;
private Context context;
// Moved a couple of variable declarations out of the onDraw method
Paint paint;
int cardWidth;
int cardHeight;
public HeartView(Context context) {
super(context);
this.context = context;
paint = new Paint();
}
Second, your math for the rects drew them beyond the borders of the screen. I put in some hard numbers just as a test. You will want to rework your numbers to get what you really want. Also, your stroke had no width, so note
#Override
public void onDraw(Canvas canvas) {
Log.println(Log.DEBUG, TAG, "onDraw fired");
canvas.drawColor(Color.DKGRAY);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(10, 10, 50, 50, paint);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
canvas.drawRect(10, 10, 50, 50, paint);
}
Third, I'm not sure what everything in onMeasure was trying to achieve, but it was causing issues for the view. You shouldn't need more than what's below:
#Override
public void onMeasure(int width, int height) {
Log.println(Log.DEBUG, TAG, "onMeasure fired");
screenWidth = width;
screenHeight = height;
Log.println(Log.DEBUG, TAG, "screenWidth = " + screenWidth);
Log.println(Log.DEBUG, TAG, "scrrenHeight = " + screenHeight);
super.onMeasure(screenWidth, screenHeight);
cardWidth = screenWidth - 10;
cardHeight = (int) (cardWidth * 1.4);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
}
Edit: note to original poster, the above is functional code tested in Eclipse. If each section is copied and pasted exactly, it will work.
Do the below changes in your onMeasure() method:
Declare the display metrics in your class.
private DisplayMetrics m_metrics;
#Override
public void onMeasure(int width, int height) {
Log.println(Log.DEBUG, TAG, "onMeasure fired");
Display m_display = getWindowManager().getDefaultDisplay();
m_metrics = context.getResources().getDisplayMetrics();
m_display.getMetrics(m_metrics);
screenWidth = m_display.getWidth();
screenHeight = m_display.getHeight();
super.onMeasure(screenWidth, screenHeight);
}

Android Progressbar with circle radius changes Dynamically

I want to change the circle radius dependent on the slider position
I created both individually.
while apply the circle method to the the Progress bar.
facing error.
Actually I call the Progress-Bar(Seek Bar) with
setContentView(R.layout.main);
and for drawing circle as you know I have to used setContentView(demoview);
Query: I want to merge both layout as display into image.
I didn't have idea will it possible or not?
Any guidance,tutorial appreciable.
Thanks for give your valuable time for my query.
Hope you have solution.
Check this out..
I am not using android seekbar, instead i am drawing a similar seekbar on canvas..
Check if this code can help u..
package com.test;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class SampleComp extends View implements OnTouchListener {
private Paint paint = null;
private int width = 0;
private int height = 0;
private int barStartX = 20;
private int barStartY = 20;
private int barEndX;
private int barEndY = 30;
private int radius;
private int heightAvailableForCircle;
private int widthAvailableForCircle;
private int maxRadius;
private int totalSeekBarLength;
private int currentSeekBarLength = 10;
private int whatPercentOfSeekBarIsSelected = 50;
public SampleComp(Context context) {
super(context);
paint = new Paint();
paint.setAntiAlias(true);
setOnTouchListener(this);
}
public SampleComp(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
paint.setAntiAlias(true);
}
public SampleComp(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
paint = new Paint();
paint.setAntiAlias(true);
}
#Override
public void onDraw(Canvas canvas){
barEndX = getWidth() - 20;
paint.setColor(Color.WHITE);
setWidth(canvas.getWidth());
setHeight(canvas.getHeight());
setHeightAvailableForCircle(getViewHeight() - barEndY);
setWidthAvailableForCircle(getViewWidth() - 40);
System.out.println("heightAvailableForCircle: "+getAvailableHeightForCircle());
System.out.println("widthAvailableForCircle: "+getWidthAvailableForCircle());
totalSeekBarLength = barEndX - barStartX;
System.out.println("SEEK LEN: "+totalSeekBarLength);
canvas.drawRect(barStartX, barStartY, barEndX, barEndY, paint);
paint.setColor(Color.BLUE);
setMaxRadius(heightAvailableForCircle, widthAvailableForCircle);
whatPercentOfSeekBarIsSelected = getSelectedSeekBarPercentage(totalSeekBarLength,getCurrentSeekBarLenghtSelected());
System.out.println("whatPercentOfSeekBarIsSelected: "+whatPercentOfSeekBarIsSelected);
System.out.println("!!!!!: "+canvas.getWidth());
System.out.println("####: "+getViewWidth());
System.out.println("^^^^^^^^^************: "+ (whatPercentOfSeekBarIsSelected * (getViewWidth() - 40)) / 100);
canvas.drawRect(barStartX, barStartY, ( (whatPercentOfSeekBarIsSelected * (getViewWidth() - 40)) / 100) + 20,
barEndY, paint);
paint.setColor(Color.GRAY);
setRadius(whatPercentOfSeekBarIsSelected);
canvas.drawCircle( (canvas.getWidth())/2, (canvas.getHeight() - 30)/2, radius, paint);
}
private void setRadius(int per){
this.radius = (getMaxRadius() * per)/100;
}
private int getSelectedSeekBarPercentage(int total, int current){
int per = 0;
per = ( (current * 100) / total);
return per;
}
private void setRadius(int total, int current){
System.out.println("total: "+total);
System.out.println("current: "+current);
this.radius = ( ( (getMaxRadius()/2) * current) / 100);
System.out.println("radius: "+this.radius);
}
private void setMaxRadius(int h, int w){
this.maxRadius = h < w ? h/2 : w/2 ;
}
private int getMaxRadius(){
return this.maxRadius;
}
private void setWidth(int w){
this.width = w;
}
private void setHeight(int h){
this.height = h;
}
private int getViewWidth(){
return this.width;
}
private int getViewHeight() {
return this.height;
}
private void setHeightAvailableForCircle(int availableHeightForCircle){
this.heightAvailableForCircle = availableHeightForCircle;
}
private int getAvailableHeightForCircle(){
return this.heightAvailableForCircle;
}
private void setWidthAvailableForCircle(int wid){
this.widthAvailableForCircle = wid;
}
private int getWidthAvailableForCircle(){
return this.widthAvailableForCircle;
}
private void setCurrentSeekBarLength(int x){
this.currentSeekBarLength = x;
}
private int getCurrentSeekBarLenghtSelected(){
return this.currentSeekBarLength;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
System.out.println("x: "+x);
System.out.println("y: "+y);
if(x >= 10 && x<= barEndX && y >= 10 && y <= 30){
System.out.println("TRUE");
setCurrentSeekBarLength(x - 20);
invalidate();
}
return false;
}
}
And this is my Activity class:
package com.test;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.widget.ImageView;
public class SampleActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleComp(this));
}
}
Can u be little more specific regarding what u want to achieve. Ur question isn't that clear. What i can make out is, u want to increase/decrease the radius of the circle based on the progress bar value.
Have a look at the android custom component guide. You basically have to derive your circle component from android.view.View. Then you can add it to your layout like every other component.

Why are .gif animated images not animating in my Android app?

I'm trying to use .gif animated images in my app, but the image is not animating. On an iPhone it works... why is Android blocking the animation? Any solution?
It looks like plenty of people are wanting animated GIFs to just work on Android, but they don't currently - see Issue 3422 on the Android bug tracker.
It looks like you may be able to do it by treating the animated GIF as a movie according to http://androidosbeginning.blogspot.com/2010/09/gif-animation-in-android.html
Similar question, which has an answer which may help you: Android: How do a display a large animated gif given a url?
you can do it like this
here is sample code.
GIFDemo1.java
import java.io.InputStream;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.Bundle;
import android.view.View;
public class GIFDemo1 extends GraphicsActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new GIFView(this));
}
private static class GIFView extends View{
Movie movie,movie1;
InputStream is=null,is1=null;
long moviestart;
long moviestart1;
public GIFView(Context context) {
super(context);
is=context.getResources().openRawResource(R.drawable.cartoon);
is1=context.getResources().openRawResource(R.drawable.animated_gif);
movie=Movie.decodeStream(is);
movie1=Movie.decodeStream(is1);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true; // this will request the bm
opts.inSampleSize = 10;
//movie=Movie.decodeFile("C:\\cartoon.gif");
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
super.onDraw(canvas);
long now=android.os.SystemClock.uptimeMillis();
System.out.println("now="+now);
if (moviestart == 0) { // first time
moviestart = now;
}
if(moviestart1==0)
{
moviestart1=now;
}
System.out.println("\tmoviestart="+moviestart);
int relTime = (int)((now - moviestart) % movie.duration()) ;
int relTime1=(int)((now - moviestart1)% movie1.duration());
System.out.println("time="+relTime+"\treltime="+movie.duration());
movie.setTime(relTime);
movie1.setTime(relTime1);
movie.draw(canvas,10,10);
movie1.draw(canvas,10,100);
this.invalidate();
}
}
}
GraphicsActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
public class GraphicsActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void setContentView(View view) {
if (false) {
// set to true to test Picture
ViewGroup vg = new PictureLayout(this);
vg.addView(view);
view = vg;
}
super.setContentView(view);
}
}
PictureLayout.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
public class PictureLayout extends ViewGroup {
private final Picture mPicture = new Picture();
public PictureLayout(Context context) {
super(context);
}
public PictureLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void addView(View child) {
if (getChildCount() > 1) {
throw new IllegalStateException("PictureLayout can host only one direct child");
}
super.addView(child);
}
#Override
public void addView(View child, int index) {
if (getChildCount() > 1) {
throw new IllegalStateException("PictureLayout can host only one direct child");
}
super.addView(child, index);
}
#Override
public void addView(View child, LayoutParams params) {
if (getChildCount() > 1) {
throw new IllegalStateException("PictureLayout can host only one direct child");
}
super.addView(child, params);
}
#Override
public void addView(View child, int index, LayoutParams params) {
if (getChildCount() > 1) {
throw new IllegalStateException("PictureLayout can host only one direct child");
}
super.addView(child, index, params);
}
#Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int count = getChildCount();
int maxHeight = 0;
int maxWidth = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
}
maxWidth += getPaddingLeft() + getPaddingRight();
maxHeight += getPaddingTop() + getPaddingBottom();
Drawable drawable = getBackground();
if (drawable != null) {
maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
}
setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
resolveSize(maxHeight, heightMeasureSpec));
}
private void drawPict(Canvas canvas, int x, int y, int w, int h,
float sx, float sy) {
canvas.save();
canvas.translate(x, y);
canvas.clipRect(0, 0, w, h);
canvas.scale(0.5f, 0.5f);
canvas.scale(sx, sy, w, h);
canvas.drawPicture(mPicture);
canvas.restore();
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
mPicture.endRecording();
int x = getWidth()/2;
int y = getHeight()/2;
if (false) {
canvas.drawPicture(mPicture);
} else {
drawPict(canvas, 0, 0, x, y, 1, 1);
drawPict(canvas, x, 0, x, y, -1, 1);
drawPict(canvas, 0, y, x, y, 1, -1);
drawPict(canvas, x, y, x, y, -1, -1);
}
}
#Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
location[0] = getLeft();
location[1] = getTop();
dirty.set(0, 0, getWidth(), getHeight());
return getParent();
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = super.getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final int childLeft = getPaddingLeft();
final int childTop = getPaddingTop();
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(),
childTop + child.getMeasuredHeight());
}
}
}
}
hope this help you.
it not work for very complex gif.

Categories

Resources