I found this class:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
// borrowed from https://sites.google.com/site/androidhowto/how-to-1/custom-scrollable-image-view
public class ScrollImageView extends View {
private final int DEFAULT_PADDING = 10;
private Display mDisplay;
private Bitmap mImage;
/* Current x and y of the touch */
private float mCurrentX = 0;
private float mCurrentY = 0;
private float mTotalX = 0;
private float mTotalY = 0;
/* The touch distance change from the current touch */
private float mDeltaX = 0;
private float mDeltaY = 0;
int mDisplayWidth;
int mDisplayHeight;
int mPadding;
public ScrollImageView(Context context) {
super(context);
initScrollImageView(context);
}
public ScrollImageView(Context context, AttributeSet attributeSet) {
super(context);
initScrollImageView(context);
}
private void initScrollImageView(Context context) {
mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mPadding = DEFAULT_PADDING;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureDim(widthMeasureSpec, mDisplay.getWidth());
int height = measureDim(heightMeasureSpec, mDisplay.getHeight());
setMeasuredDimension(width, height);
}
private int measureDim(int measureSpec, int size) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = size;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
public Bitmap getImage() {
return mImage;
}
public void setImage(Bitmap image) {
mImage = image;
}
public int getPadding() {
return mPadding;
}
public void setPadding(int padding) {
this.mPadding = padding;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mCurrentX = event.getRawX();
mCurrentY = event.getRawY();
}
else if (event.getAction() == MotionEvent.ACTION_MOVE) {
float x = event.getRawX();
float y = event.getRawY();
// Update how much the touch moved
mDeltaX = x - mCurrentX;
mDeltaY = y - mCurrentY;
mCurrentX = x;
mCurrentY = y;
invalidate();
}
// Consume event
return true;
}
#Override
protected void onDraw(Canvas canvas) {
if (mImage == null) {
return;
}
float newTotalX = mTotalX + mDeltaX;
// Don't scroll off the left or right edges of the bitmap.
if (mPadding > newTotalX && newTotalX > getMeasuredWidth() - mImage.getWidth() - mPadding)
mTotalX += mDeltaX;
float newTotalY = mTotalY + mDeltaY;
// Don't scroll off the top or bottom edges of the bitmap.
if (mPadding > newTotalY && newTotalY > getMeasuredHeight() - mImage.getHeight() - mPadding)
mTotalY += mDeltaY;
Paint paint = new Paint();
canvas.drawBitmap(mImage, mTotalX, mTotalY, paint);
}
}
and am stumped how to use it with my application.
I want my application when in landscape orientation to display a bitmap image that is scrollable vertically and horizontally. I pull my image from a URL and programatically make it a bitmap. I call a method that returns my bitmap image.
Any ideas?
The setImage methods takes a Bitmap. So, you should be able to programmatically create this view in your activity, set the image with your Bitmap and place the view into your layout.
I've never seen this class before, so your mileage may vary ;)
Related
This is my code below but its not working. I am trying to draw a background image, and then have random sparkles and glitter effects randomly show on the screen. All I get is a black screen.
package com.griffslabs.glitterlwptest;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import java.util.ArrayList;
import java.util.Random;
public class RainbowSparkleWallpaperService extends WallpaperService {
#Override
public Engine onCreateEngine() {
return new RainbowSparkleEngine();
}
class RainbowSparkleEngine extends Engine {
private ArrayList<Sparkle> sparkles = new ArrayList<>();
private ArrayList<GlitterTrail> glitterTrails = new ArrayList<>();
private Paint paint = new Paint();
private int sparkleSize = 5;
private int glitterTrailSize = 10;
private int sparkleSpeed = 5;
private int glitterTrailSpeed = 2;
private int width;
private int height;
private Random random = new Random();
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
this.width = width;
this.height = height;
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
int x = (int) event.getX();
int y = (int) event.getY();
sparkles.add(new Sparkle(x, y, sparkleSize, sparkleSpeed));
glitterTrails.add(new GlitterTrail(x, y, glitterTrailSize, glitterTrailSpeed));
}
private class DrawThread extends Thread {
private boolean running = false;
private SurfaceHolder surfaceHolder;
DrawThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
void setRunning(boolean running) {
this.running = running;
}
#Override
public void run() {
Canvas canvas;
while (running) {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
Rect frame = surfaceHolder.getSurfaceFrame();
onDraw(canvas, frame);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
public void onDraw(Canvas canvas, Rect frame) {
canvas.drawBitmap(getBackgroundImage(), null, frame, null);
for (int i = 0; i < sparkles.size(); i++) {
Sparkle sparkle = sparkles.get(i);
paint.setColor(sparkle.color);
canvas.drawCircle(sparkle.x, sparkle.y, sparkle.size, paint);
sparkle.update();
if (sparkle.y + sparkle.size < 0 || sparkle.y - sparkle.size > height) {
sparkles.remove(sparkle);
}
}
for (int i = 0; i < glitterTrails.size(); i++) {
GlitterTrail glitterTrail = glitterTrails.get(i);
paint.setColor(glitterTrail.color);
canvas.drawRect(glitterTrail.x, glitterTrail.y, glitterTrail.x + glitterTrail.size, glitterTrail.y + glitterTrail.size, paint);
glitterTrail.update();
if (glitterTrail.y + glitterTrail.size < 0 || glitterTrail.y - glitterTrail.size > height) {
glitterTrails.remove(glitterTrail);
}
}
}
private Bitmap getBackgroundImage() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.background, options);
background = Bitmap.createScaledBitmap(background, width, height, true);
return background;
}
private class Sparkle {
int x;
int y;
int size;
int speed;
int color;
Sparkle(int x, int y, int size, int speed) {
this.x = x;
this.y = y;
this.size = size;
this.speed = speed;
this.color = getRandomColor();
}
void update() {
y -= speed;
}
int getRandomColor() {
int[] rainbowColors = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};
return rainbowColors[random.nextInt(rainbowColors.length)];
}
}
private class GlitterTrail {
int x;
int y;
int size;
int speed;
int color;
GlitterTrail(int x, int y, int size, int speed) {
this.x = x;
this.y = y;
this.size = size;
this.speed = speed;
this.color = getRandomColor();
}
void update() {
y -= speed;
}
int getRandomColor() {
int[] rainbowColors = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};
return rainbowColors[random.nextInt(rainbowColors.length)];
}
}
}
}
expecting it to work. I have tried almost everything and it just does not work. any input will be aprecciated.
I have tried to implement the youtube like draggable panel using the Customlayout which extends ViewGroup. I have made use of the onTouchEvents to create and scaling on dragging effect.
Now, the problem is that the when dragged down, the selected item resides near the bottom of the screen as it happens in YouTube. When clicked on that item in that position, it should get back to the full screen mode. But to do so, I implemented the onClicklistener for the view but it simply doesn't respond.
Also, when at the bottom, how do I restrict it's motion in the vertical direction and allow it to move in the horizontal direction as it happens in YouTube.
Here is the CustomLayout class called DraggablePanel.
package visio.com.eventpage;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.Toast;
import static android.view.MotionEvent.INVALID_POINTER_ID;
/**
* Created by Rambo on 1/9/2018.
*/
public class DraggablePanel extends ViewGroup {
public final ViewDragHelper mDragHelper;
public View mHeaderView;
private View mDescView;
private float mInitialMotionX;
private float mInitialMotionY;
private int mDragRange;
private int mTop;
private float mDragOffset;
private Context context;
public int toponViewReleased;
public int screenWidth, screenHeight;
private String TAG = "DraggablePanel";
public void manualInvalidate(){
invalidate();
}
public DraggablePanel(Context context) {
this(context, null);
}
public DraggablePanel(Context context, AttributeSet attrs) {
this(context, attrs, 0);
this.context = context;
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
mHeaderView = findViewById(R.id.viewHeader);
mDescView = findViewById(R.id.viewDesc);
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
screenHeight = displayMetrics.heightPixels;
screenWidth = displayMetrics.widthPixels;
}
public DraggablePanel(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mDragHelper = ViewDragHelper.create(this, 1f, new DragHelperCallback());
}
private class DragHelperCallback extends ViewDragHelper.Callback {
#Override
public boolean tryCaptureView(View child, int pointerId) {
return child == mHeaderView;
}
#Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
mTop = top;
float paddingOffset = (float)top/10;
mDragOffset = (float) top / mDragRange;
mHeaderView.setPivotX(mHeaderView.getWidth());
mHeaderView.setPivotY(mHeaderView.getHeight());
mHeaderView.setScaleX(1 - mDragOffset / 2);
mHeaderView.setScaleY(1 - mDragOffset / 2);
mHeaderView.setPadding(0,0,(int) paddingOffset, (int) paddingOffset);
mDescView.setAlpha(1 - mDragOffset);
if( top == 0){
}
requestLayout();
Log.d("onViewPositionChanged","Called");
}
#Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
int top = releasedChild.getTop()>screenHeight/3?screenHeight-150 - mHeaderView.getHeight():0;
Log.d("Heights","H1"+getHeight() + "child height" + releasedChild.getMeasuredHeight()+"top" +top);
mDragHelper.smoothSlideViewTo(releasedChild, releasedChild.getLeft(),top);
if( top!=0 ){
mDescView.setAlpha(0);
}
ViewCompat.postInvalidateOnAnimation(releasedChild);
toponViewReleased = top;
invalidate();
}
#Override
public int getViewVerticalDragRange(View child) {
return mDragRange;
}
#Override
public int clampViewPositionVertical(View child, int top, int dy) {
float descViewAlpha = mDescView.getAlpha();
final int topBound = getPaddingTop();
final int bottomBound = getHeight() - mHeaderView.getHeight() - 20;
int newTop = Math.min(Math.max(top, topBound), bottomBound);
if( descViewAlpha == 0 ){
newTop = 0;
}
Log.d(TAG,"clampVertical" + newTop);
return newTop;
}
#Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
final int rightBound = mHeaderView.getPaddingRight();
final int leftBound = screenWidth - mHeaderView.getWidth() - 20;
int newTop = Math.min(Math.max(left, rightBound), leftBound);
if(mDescView.getAlpha() != 0){
newTop = 0;
}
Log.d(TAG,"clampHorizontal" + newTop);
return newTop;
}
}
#Override
public void computeScroll() {
if (mDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
if (( action != MotionEvent.ACTION_DOWN)) {
mDragHelper.cancel();
return super.onInterceptTouchEvent(ev);
}
final float x = ev.getX();
final float y = ev.getY();
boolean interceptTap = false;
switch (action) {
case MotionEvent.ACTION_DOWN: {
mInitialMotionX = x;
mInitialMotionY = y;
interceptTap = mDragHelper.isViewUnder(mHeaderView, (int) x, (int) y);
break;
}
case MotionEvent.ACTION_MOVE: {
final float adx = Math.abs(x - mInitialMotionX);
final float ady = Math.abs(y - mInitialMotionY);
final int slop = mDragHelper.getTouchSlop();
if (ady > slop && adx > ady) {
mDragHelper.cancel();
return false;
}
}
}
return mDragHelper.shouldInterceptTouchEvent(ev) || interceptTap;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
mDragHelper.processTouchEvent(ev);
final int action = ev.getAction();
final float x = ev.getX();
final float y = ev.getY();
boolean isHeaderViewUnder = mDragHelper.isViewUnder(mHeaderView, (int) x, (int) y);
switch (action & ev.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
mInitialMotionX = x;
mInitialMotionY = y;
break;
}
}
return isHeaderViewUnder && isViewHit(mHeaderView, (int) x, (int) y) || isViewHit(mDescView, (int) x, (int) y);
}
#Override
public boolean performClick() {
super.performClick();
if(toponViewReleased !=0){
mDragHelper.smoothSlideViewTo(mHeaderView, 0,0);
invalidate();
Log.d("DraggablePanel","Clicked top != 0");
}else{
Log.d("DraggablePanel","Clicked top == 0");
}
return true;
}
private boolean isViewHit(View view, int x, int y) {
int[] viewLocation = new int[2];
view.getLocationOnScreen(viewLocation);
int[] parentLocation = new int[2];
this.getLocationOnScreen(parentLocation);
int screenX = parentLocation[0] + x;
int screenY = parentLocation[1] + y;
return screenX >= viewLocation[0] && screenX < viewLocation[0] + view.getWidth() &&
screenY >= viewLocation[1] && screenY < viewLocation[1] + view.getHeight();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, 0),
resolveSizeAndState(maxHeight, heightMeasureSpec, 0));
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.d(TAG,"onLayout Called");
mDragRange = getHeight() - mHeaderView.getHeight();
mHeaderView.layout(
0,
mTop,
r,
mTop + mHeaderView.getMeasuredHeight());
mDescView.layout(
0,
mTop + mHeaderView.getMeasuredHeight(),
r,
mTop + b);
}
}
Here is the Layout where the above class has been used.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerViewEvents"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<visio.com.eventpage.DraggablePanel
android:id="#+id/draggablePanel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone">
<ImageView
android:id="#+id/viewHeader"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginEnd="20dp"
android:gravity="center"
android:scaleType="fitXY"
android:src="#drawable/ic_event" />
<TextView
android:id="#+id/viewDesc"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF00FF"
android:gravity="center"
android:tag="desc"
android:text="Loreum Loreum"
android:textColor="#android:color/white"
android:textSize="35sp" />
</visio.com.eventpage.DraggablePanel>
</FrameLayout>
am looking to create a customs slider component with the functionality of s seek bar.
I have been following this tutorial
http://www.androidenea.com/2011/10/creating-custom-view-part-1-graphics.html
however, I wish to use my own graphics which aren't .9.png graphics. I also need to resize the seek bar and the slider.
If anyone can help on this I'd greatly appreciate it. I have it to a stage where I have it resized and the graphics are changed however, when I use my finger to slide upwards I need to slide to the top of the screen in order for my seebar to reach the top of the frame.
Please any help is appreciated, this is what I've implemented so far:
package com.enea.training.customview;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class CustomSlider extends View {
interface CustomSliderPositionListener {
void onPositionChange(float newPosition);
}
private final Drawable mIndicator;
private final Drawable mBackground;
private float mMin;
private float mMax;
private float mPosition;
private Rect mViewRect;
private int mIndicatorOffset;
private int mIndicatorMaxPos;
private int mIndicatorMinPos;
private CustomSliderPositionListener mPositionListener;
private boolean mIsVertical;
public CustomSlider(final Context context) {
this(context, null, 0);
}
public CustomSlider(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomSlider(final Context context, final AttributeSet attrs,
final int defStyle) {
super(context, attrs, defStyle);
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CustomSlider);
final int vertical = a.getInt(R.styleable.CustomSlider_orientation, 0);
mIsVertical = (vertical != 0);
final float max = a.getFloat(R.styleable.CustomSlider_max, 1.0f);
final float min = a.getFloat(R.styleable.CustomSlider_min, -1.0f);
setMinMax(min, max);
final Resources res = context.getResources();
if (mIsVertical) {
mIndicator = res.getDrawable(R.drawable.beer_with_arrows);
mBackground = res.getDrawable(R.drawable.glass);
} else {
mIndicator = res.getDrawable(R.drawable.indicator_horizontal);
mBackground = res.getDrawable(R.drawable.background_horizontal);
}
mPosition =(mMax - 1) ;/// 2 + mMin;
mPositionListener = null;
setOnTouchListener(new OnTouchListener() {
public boolean onTouch(final View v, final MotionEvent event) {
final float pos;
if (mIsVertical) {
float divisor = mIndicatorMinPos-mIndicatorMaxPos;
pos = (mMax - ((mMax - mMin) / divisor)
* event.getY());
} else {
pos = (mMin + ((mMax - mMin) / (mIndicatorMaxPos - mIndicatorMinPos))
* event.getX());
}
setPosition(pos);
return true;
}
});
}
#Override
protected void onDraw(final Canvas canvas) {
if (mViewRect == null) {
mViewRect = new Rect();
mViewRect.set(20,20,20,20);
getDrawingRect(mViewRect);
if (mIsVertical) {
mIndicatorOffset = mIndicator.getIntrinsicHeight();
mIndicatorMaxPos = mViewRect.top + mIndicatorOffset;
mIndicatorMinPos = mViewRect.bottom - mIndicatorOffset;
} else {
mIndicatorOffset = mIndicator.getIntrinsicWidth();
mIndicatorMaxPos = mViewRect.right - mIndicatorOffset;
mIndicatorMinPos = mViewRect.left + mIndicatorOffset;
}
mBackground.setBounds(mViewRect.left, mViewRect.top, mViewRect.right,
mViewRect.bottom);
}
final float pos;
final int left;
final int right;
final int top;
final int bottom;
if (mIsVertical) {
pos = mIndicatorMaxPos
+ ((mIndicatorMinPos - mIndicatorMaxPos) / (mMax - mMin))
* (mMax - mPosition);
left = mViewRect.centerX() - (mIndicator.getIntrinsicWidth() / 2);
top = (int) pos - (mBackground.getIntrinsicHeight() / 2);
} else {
pos = mIndicatorMinPos
+ ((mIndicatorMaxPos - mIndicatorMinPos) / (mMax - mMin))
* (mPosition - mMin);
left = (int) pos - (mIndicator.getIntrinsicWidth() / 2);
top = mViewRect.centerY() - (mIndicator.getIntrinsicHeight() / 2);
}
right = left + mIndicator.getIntrinsicWidth();
bottom = top + mIndicator.getIntrinsicHeight();
mIndicator.setBounds(left, top, right, bottom);
mIndicator.draw(canvas);
mBackground.draw(canvas);
}
#Override
protected void onMeasure(final int widthMeasureSpec,
final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mIsVertical) {
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
//setMeasuredDimension(getSuggestedMinimumWidth(),getSuggestedMinimumHeight());
// setMeasuredDimension(mIndicator.getIntrinsicWidth(), getMeasuredHeight());
} else {
setMeasuredDimension(getMeasuredWidth(), mBackground.getIntrinsicHeight());
}
}
public float getMin() {
return mMin;
}
public float getMax() {
return mMax;
}
public float getPosition() {
return mPosition;
}
public void setPosition(float position) {
position = within(position, mMin, mMax);
if (position != mPosition) {
mPosition = position;
invalidate();
if (mPositionListener != null) {
mPositionListener.onPositionChange(mPosition);
}
}
}
private static float within(float position, final float min, final float max) {
if (position < min) {
position = min;
}
if (position > max) {
position = max;
}
return position;
}
public void setMinMax(final float min, final float max) {
if ((min != mMin) || (max != mMax)) {
if (min > max) {
throw new IllegalArgumentException(
"setMinMax: min must be smaller than max.");
}
mMin = min;
mMax = max;
setPosition(mPosition);
invalidate();
}
}
public void setPositionListener(final CustomSliderPositionListener listener) {
mPositionListener = listener;
}
}
****EDIT****
So below I have done up a rough pic to show what I'm trying to do. So my custom view includes the slider, and frame (background and indicator). The slider (indicator) is dragged by user up and down inside the red background..
I would apprecaite any help and thank you for your help so far...
I
I wrote a Compass example that came out of an Android application tutorial book and wrote the custom view, methods, and such, but nothing is being drawn on the screen when the app runs.
Here is the class:
package com.example.compass;
import android.view.View;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityEvent;
public class CompassView extends View {
private float bearing;
private Paint markerPaint;
private Paint textPaint;
private Paint circlePaint;
private String northString;
private String eastString;
private String southString;
private String westString;
private int textHeight;
public CompassView(Context context) {
super(context);
initCompassView();
}
public CompassView(Context context, AttributeSet attrs) {
super(context, attrs);
initCompassView();
}
public CompassView(Context context, AttributeSet ats, int defaultStyle) {
super(context, ats, defaultStyle);
initCompassView();
}
protected void initCompassView() {
setFocusable(true);
Resources r = this.getResources();
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(r.getColor(R.color.background_color));
circlePaint.setStrokeWidth(1);
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
northString = r.getString(R.string.cardinal_north);
eastString = r.getString(R.string.cardinal_east);
southString = r.getString(R.string.cardinal_south);
westString = r.getString(R.string.cardinal_west);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(r.getColor(R.color.text_color));
textHeight = (int)textPaint.measureText("yY");
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
markerPaint.setColor(r.getColor(R.color.marker_color));
}
#Override
protected void onDraw(Canvas canvas) {
int mMeasuredWidth = getMeasuredWidth();
int mMeasuredHeight = getMeasuredHeight();
int px = mMeasuredWidth/2;
int py = mMeasuredHeight/2;
int radius = Math.min(px, py);
canvas.drawCircle(px, py, radius, circlePaint);
canvas.save();
canvas.rotate(-bearing, px, py);
int textWidth = (int) textPaint.measureText("W");
int cardinalX = px-textWidth/2;
int cardinalY = py-radius+textHeight;
for (int i = 0; i < 24; i++) {
canvas.drawLine(px, py-radius, px, py-radius+10, markerPaint);
canvas.save();
canvas.translate(0, textWidth);
if (i%6 == 0) {
String dirString = "";
switch (i) {
case(0):{
dirString = northString;
int arrowY = 2*textHeight;
canvas.drawLine(px, arrowY, px-5, 3*textHeight, markerPaint);
canvas.drawLine(px, arrowY, px+5, 3*textHeight, markerPaint);
break;
}
case(6): dirString = eastString; break;
case(12): dirString = southString; break;
case(18): dirString = westString; break;
}
canvas.drawText(dirString, cardinalX, cardinalY, textPaint);
}
else if (i%3==0) {
String angle = String.valueOf(i*15);
float angleTextWidth = textPaint.measureText(angle);
int angleTextX = (int)(px-angleTextWidth/2);
int angleTextY = py-radius+textHeight;
canvas.drawText(angle, angleTextX, angleTextY, textPaint);
}
canvas.restore();
canvas.rotate(15, px, py);
}
canvas.restore();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
int d = Math.min(measuredWidth, measuredHeight);
setMeasuredDimension(d, d);
}
private int measure(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getMode(measureSpec);
if (specMode == MeasureSpec.UNSPECIFIED) {
result = 200;
}
else {
result = specSize;
}
return result;
}
public void setBearing(float _bearing) {
bearing = _bearing;
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
}
public float getBearing() {
return bearing;
}
#SuppressWarnings("deprecation")
#Override
public boolean dispatchPopulateAccessibilityEvent(final AccessibilityEvent event) {
super.dispatchPopulateAccessibilityEvent(event);
if (isShown()) {
String bearingStr = String.valueOf(bearing);
if (bearingStr.length() > AccessibilityEvent.MAX_TEXT_LENGTH)
bearingStr = bearingStr.substring(0, AccessibilityEvent.MAX_TEXT_LENGTH);
event.getText().add(bearingStr);
return true;
}
else
return false;
}
}
I don't get any logcat errors; it does however display this (which might be relevant):
04-01 18:41:57.163: D/gralloc_goldfish(583): Emulator without GPU emulation detected.
However, after seeing this I added GPU emulation hardware to my emulator and selected the "Yes" option, but this message keeps showing up.
What could be the cause of nothing displaying on the screen? I can also post xml files if needed.
Figured out the cause: called getMode a second time instead of getSize... I feel dumb now.
I currently have something working where I can drag a box horizontally on the screen (what I want it to do). However, it works when you click ANYWHERE on the screen, and I want it to work only when the box has been clicked. I have tried implementing this in different ways, and I've looked all over the place and still remain lost. Can anybody help? I also can't figure out how a bitmap is placed (I'm using a bitmap right now as I can't for the life of me figure out how to implement the ImageView inside my SurfaceView). If I say my bitmap is placed at 0,0 will that place the bitmap according to its top left corner at 0,0? I also had an algorithm for stopping the box when it reached an edge, but I'll just have to rewrite that as I must have deleted it. Please if you can offer your knowledge I would GREATLY appreciate it
public class BoardView extends SurfaceView implements SurfaceHolder.Callback{
Context mContext;
private BoardThread thread;
private float box_x = 140;
private float box_y = 378;
ImageView i = (ImageView) findViewById(R.id.box_view);
Bitmap box =
(BitmapFactory.decodeResource
(getResources(), R.drawable.box));
private float boxWidth = box.getWidth();
private float boxHeight = box.getHeight();
public BoardView(Context context){
super(context);
//surfaceHolder provides canvas that we draw on
getHolder().addCallback(this);
// controls drawings
thread = new BoardThread(getHolder(),this);
//intercepts touch events
setFocusable(true);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawColor(Color.WHITE);
//draw box and set start location
canvas.drawBitmap(box, box_x - (boxWidth/2),
box_y - (boxHeight/2), null);
}
#Override
public boolean onTouchEvent(MotionEvent event){
//boolean mode = false;
if(event.getAction() == MotionEvent.ACTION_DOWN){
//int x = (int)event.getX();
//int y = (int)event.getY();
//if (x > box_x && x < box_x + 29 && y > box_y && y < box_y + 30){
//mode = true;
box_x = (int)event.getX();
//}
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
//int x = (int)event.getX();
//int y = (int)event.getY();
//if (mode == true){
box_x = (int)event.getX();
//}
}
invalidate();
return true;
}
#Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height ){
}
#Override
public void surfaceCreated(SurfaceHolder holder){
thread.startRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder){
thread.startRunning(false);
thread.stop();
}
}
Simply check the touch event x and y coordinate, and check if this x,y-combination is within the box's bounds. I can see you are on the right path by looking at your commented out code.
Do something like this:
RectF rect = new RectF(x,y, x + box.getWidth(), y+box.geHeight());
if(rect.contains(touchX, touchY)) {
// You hit the box, allow dragging...
}
Try this:
package teste.com.br.teste;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Tacila on 03/07
*/
public class Game extends View {
private Context context;
private BitmaptArrastavel bmArrastavel;
private BitmaptArrastavel bmArrastavel2;
private BitmaptArrastavel bmArrastavelTeste;
private List<BitmaptArrastavel> btms;
private BitmaptArrastavel[] btmsAtivas;
private BitmaptArrastavel[] lake;
private BitmaptArrastavel[] ativos;
private int qntDeItens = 5;
public Game(Context context) {
super(context);
this.context = context;
init();
}
public void init() {
btms = new ArrayList<BitmaptArrastavel>();
btmsAtivas = new BitmaptArrastavel[1];
ativos=new BitmaptArrastavel[1];
lake = new BitmaptArrastavel[3];
lake[0] = new BitmaptArrastavel(escalaBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.cartadc)), 200);
lake[1] = new BitmaptArrastavel(escalaBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.cartaao)), 210);
lake[2] = new BitmaptArrastavel(escalaBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.cartake)), 220);
btms.add(bmArrastavel);
btms.add(bmArrastavelTeste);
btms.add(bmArrastavel2);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRGB(0,0,139);
for(int i = 0; i<=2; i++){
lake[i].drawOnCanvas(canvas);
}
}
public void travarArr(float x, float y ){
for(int i = 0; i<=2 ; i++){
if(lake[i].isDentro(x,y)){
ativos[0]=lake[i];
}
}
}
public void destravarBitmap() {
ativos[0]=null;
}
public Bitmap escalaBitmap(Bitmap bm) {
return Bitmap.createScaledBitmap(bm, 200, 300, false);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
System.out.println("Dentro do MotionEvent.ActionDown");
travarArr(event.getX(),event.getY());
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
System.out.println("Dentro do MotionEvent.ActionUP e ActionCancel tenho q entrar no destrava ");
destravarBitmap();
break;
case MotionEvent.ACTION_MOVE:
System.out.println("Dentro do MotionEvent.ActionMove");
for(int i = 0; i<ativos.length;i++){
if(ativos[i]!=null){
ativos[i].mover((int)event.getX(),(int)event.getY());
invalidate();
}
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
System.out.println("Dentro do MotionEvent.ActionPointerDown");
travarArr(event.getX(), event.getY());
break;
case MotionEvent.ACTION_POINTER_UP:
System.out.println("Dentro do MotionEvent.ActionPointerUp");
destravarBitmap();
break;
default:
return super.onTouchEvent(event);
}
return true;
}
// int rotation = 0;
//
// public Bitmap vertical() {
// Matrix matrix = new Matrix();
// matrix.postRotate(90);
// Bitmap bm = escalaBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.carta4c));
// return Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
// }
}
The class BitmapArrastavel
package teste.com.br.teste;
import android.graphics.Bitmap;
import android.graphics.Canvas;
/**
* Created by Tacila on 05/07/2017.
*/
public class BitmaptArrastavel {
public int x, y, altura, largura;
private Bitmap bitmap;
public BitmaptArrastavel(Bitmap b, int x) {
bitmap = b;
this.x = x;
init();
}
public void init() {
largura = 200;
altura = 350;
}
public Bitmap escalaBitmap(Bitmap bm) {
return Bitmap.createScaledBitmap(bm, largura, altura, false);
}
public boolean isDentro(float x, float y) {
return (x >= this.x && x <= this.x + largura && y >= this.y && y <= this.y + altura);
}
public void drawOnCanvas(Canvas canvas) {
canvas.drawBitmap(bitmap, x, y, null);
}
public void mover(int x, int y) {
this.x = x;
this.y = y;
}
}