Change Radius of arc - java

I am using this Github Library https://github.com/lzyzsd/CircleProgress.
But i am not getting how to increse size of arc or chane its circumference means its starting and ending point .
I am unable to it ,please help in it .
Here is my xml code.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:background="#4a4a4a" xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Player Header -->
<!-- Progress Bar/Seek bar -->
<com.androidhive.musicplayer.equalizer.ArcProgress
android:id="#+id/songProgressBar"
android:background="#214193"
android:layout_marginLeft="50dp"
android:layout_width="100dp"
android:layout_height="100dp"
custom:arc_progress="55"
custom:arc_bottom_text="MEMORY"/>
</RelativeLayout>
Here is ArcProgress.java
package com.androidhive.musicplayer.equalizer;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import com.androidhive.musicplayer.R;
/**
* Created by bruce on 11/6/14.
*/
public class ArcProgress extends View {
private Paint paint;
protected Paint textPaint;
private RectF rectF = new RectF();
private float strokeWidth;
private float suffixTextSize;
private float bottomTextSize;
private String bottomText;
private float textSize;
private int textColor;
private int progress = 0;
private int max;
private int finishedStrokeColor;
private int unfinishedStrokeColor;
private float arcAngle;
private String suffixText = "%";
private float suffixTextPadding;
private float arcBottomHeight;
private final int default_finished_color = Color.WHITE;
private final int default_unfinished_color = Color.rgb(72, 106, 176);
private final int default_text_color = Color.rgb(66, 145, 241);
private final float default_suffix_text_size;
private final float default_suffix_padding;
private final float default_bottom_text_size;
private final float default_stroke_width;
private final String default_suffix_text;
private final int default_max = 100;
private final float default_arc_angle = 360 * 0.8f;
private float default_text_size;
private final int min_size;
private static final String INSTANCE_STATE = "saved_instance";
private static final String INSTANCE_STROKE_WIDTH = "stroke_width";
private static final String INSTANCE_SUFFIX_TEXT_SIZE = "suffix_text_size";
private static final String INSTANCE_SUFFIX_TEXT_PADDING = "suffix_text_padding";
private static final String INSTANCE_BOTTOM_TEXT_SIZE = "bottom_text_size";
private static final String INSTANCE_BOTTOM_TEXT = "bottom_text";
private static final String INSTANCE_TEXT_SIZE = "text_size";
private static final String INSTANCE_TEXT_COLOR = "text_color";
private static final String INSTANCE_PROGRESS = "progress";
private static final String INSTANCE_MAX = "max";
private static final String INSTANCE_FINISHED_STROKE_COLOR = "finished_stroke_color";
private static final String INSTANCE_UNFINISHED_STROKE_COLOR = "unfinished_stroke_color";
private static final String INSTANCE_ARC_ANGLE = "arc_angle";
private static final String INSTANCE_SUFFIX = "suffix";
public ArcProgress(Context context) {
this(context, null);
}
public ArcProgress(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ArcProgress(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
default_text_size = Utils.sp2px(getResources(), 18);
min_size = (int) Utils.dp2px(getResources(), 100);
default_text_size = Utils.sp2px(getResources(), 40);
default_suffix_text_size = Utils.sp2px(getResources(), 15);
default_suffix_padding = Utils.dp2px(getResources(), 4);
default_suffix_text = "%";
default_bottom_text_size = Utils.sp2px(getResources(), 10);
default_stroke_width = Utils.dp2px(getResources(), 4);
TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcProgress, defStyleAttr, 0);
initByAttributes(attributes);
attributes.recycle();
initPainters();
}
protected void initByAttributes(TypedArray attributes) {
finishedStrokeColor = attributes.getColor(R.styleable.ArcProgress_arc_finished_color, default_finished_color);
unfinishedStrokeColor = attributes.getColor(R.styleable.ArcProgress_arc_unfinished_color, default_unfinished_color);
textColor = attributes.getColor(R.styleable.ArcProgress_arc_text_color, default_text_color);
textSize = attributes.getDimension(R.styleable.ArcProgress_arc_text_size, default_text_size);
arcAngle = attributes.getFloat(R.styleable.ArcProgress_arc_angle, default_arc_angle);
setMax(attributes.getInt(R.styleable.ArcProgress_arc_max, default_max));
setProgress(attributes.getInt(R.styleable.ArcProgress_arc_progress, 0));
strokeWidth = attributes.getDimension(R.styleable.ArcProgress_arc_stroke_width, default_stroke_width);
suffixTextSize = attributes.getDimension(R.styleable.ArcProgress_arc_suffix_text_size, default_suffix_text_size);
suffixText = TextUtils.isEmpty(attributes.getString(R.styleable.ArcProgress_arc_suffix_text)) ? default_suffix_text : attributes.getString(R.styleable.ArcProgress_arc_suffix_text);
suffixTextPadding = attributes.getDimension(R.styleable.ArcProgress_arc_suffix_text_padding, default_suffix_padding);
bottomTextSize = attributes.getDimension(R.styleable.ArcProgress_arc_bottom_text_size, default_bottom_text_size);
bottomText = attributes.getString(R.styleable.ArcProgress_arc_bottom_text);
}
protected void initPainters() {
textPaint = new TextPaint();
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
textPaint.setAntiAlias(true);
paint = new Paint();
paint.setColor(default_unfinished_color);
paint.setAntiAlias(true);
paint.setStrokeWidth(strokeWidth);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
}
#Override
public void invalidate() {
initPainters();
super.invalidate();
}
public float getStrokeWidth() {
return strokeWidth;
}
public void setStrokeWidth(float strokeWidth) {
this.strokeWidth = strokeWidth;
this.invalidate();
}
public float getSuffixTextSize() {
return suffixTextSize;
}
public void setSuffixTextSize(float suffixTextSize) {
this.suffixTextSize = suffixTextSize;
this.invalidate();
}
public String getBottomText() {
return bottomText;
}
public void setBottomText(String bottomText) {
this.bottomText = bottomText;
this.invalidate();
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
if (this.progress > getMax()) {
this.progress %= getMax();
}
invalidate();
}
public int getMax() {
return max;
}
public void setMax(int max) {
if (max > 0) {
this.max = max;
invalidate();
}
}
public float getBottomTextSize() {
return bottomTextSize;
}
public void setBottomTextSize(float bottomTextSize) {
this.bottomTextSize = bottomTextSize;
this.invalidate();
}
public float getTextSize() {
return textSize;
}
public void setTextSize(float textSize) {
this.textSize = textSize;
this.invalidate();
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
this.invalidate();
}
public int getFinishedStrokeColor() {
return finishedStrokeColor;
}
public void setFinishedStrokeColor(int finishedStrokeColor) {
this.finishedStrokeColor = finishedStrokeColor;
this.invalidate();
}
public int getUnfinishedStrokeColor() {
return unfinishedStrokeColor;
}
public void setUnfinishedStrokeColor(int unfinishedStrokeColor) {
this.unfinishedStrokeColor = unfinishedStrokeColor;
this.invalidate();
}
public float getArcAngle() {
return arcAngle;
}
public void setArcAngle(float arcAngle) {
this.arcAngle = arcAngle;
this.invalidate();
}
public String getSuffixText() {
return suffixText;
}
public void setSuffixText(String suffixText) {
this.suffixText = suffixText;
this.invalidate();
}
public float getSuffixTextPadding() {
return suffixTextPadding;
}
public void setSuffixTextPadding(float suffixTextPadding) {
this.suffixTextPadding = suffixTextPadding;
this.invalidate();
}
#Override
protected int getSuggestedMinimumHeight() {
return min_size;
}
#Override
protected int getSuggestedMinimumWidth() {
return min_size;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
rectF.set(strokeWidth / 2f, strokeWidth / 2f, width - strokeWidth / 2f, MeasureSpec.getSize(heightMeasureSpec) - strokeWidth / 2f);
float radius = width / 2f;
float angle = (360 - arcAngle) / 2f;
arcBottomHeight = radius * (float) (1 - Math.cos(angle / 180 * Math.PI));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float startAngle = 270 - arcAngle / 2f;
float finishedSweepAngle = progress / (float) getMax() * arcAngle;
float finishedStartAngle = startAngle;
paint.setColor(unfinishedStrokeColor);
canvas.drawArc(rectF, startAngle, arcAngle, false, paint);
paint.setColor(finishedStrokeColor);
canvas.drawArc(rectF, finishedStartAngle, finishedSweepAngle, false, paint);
String text = String.valueOf(getProgress());
if (!TextUtils.isEmpty(text)) {
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
float textHeight = textPaint.descent() + textPaint.ascent();
float textBaseline = (getHeight() - textHeight) / 2.0f;
canvas.drawText(text, (getWidth() - textPaint.measureText(text)) / 2.0f, textBaseline, textPaint);
textPaint.setTextSize(suffixTextSize);
float suffixHeight = textPaint.descent() + textPaint.ascent();
canvas.drawText(suffixText, getWidth() / 2.0f + textPaint.measureText(text) + suffixTextPadding, textBaseline + textHeight - suffixHeight, textPaint);
}
if (!TextUtils.isEmpty(getBottomText())) {
textPaint.setTextSize(bottomTextSize);
float bottomTextBaseline = getHeight() - arcBottomHeight - (textPaint.descent() + textPaint.ascent()) / 2;
canvas.drawText(getBottomText(), (getWidth() - textPaint.measureText(getBottomText())) / 2.0f, bottomTextBaseline, textPaint);
}
}
#Override
protected Parcelable onSaveInstanceState() {
final Bundle bundle = new Bundle();
bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
bundle.putFloat(INSTANCE_STROKE_WIDTH, getStrokeWidth());
bundle.putFloat(INSTANCE_SUFFIX_TEXT_SIZE, getSuffixTextSize());
bundle.putFloat(INSTANCE_SUFFIX_TEXT_PADDING, getSuffixTextPadding());
bundle.putFloat(INSTANCE_BOTTOM_TEXT_SIZE, getBottomTextSize());
bundle.putString(INSTANCE_BOTTOM_TEXT, getBottomText());
bundle.putFloat(INSTANCE_TEXT_SIZE, getTextSize());
bundle.putInt(INSTANCE_TEXT_COLOR, getTextColor());
bundle.putInt(INSTANCE_PROGRESS, getProgress());
bundle.putInt(INSTANCE_MAX, getMax());
bundle.putInt(INSTANCE_FINISHED_STROKE_COLOR, getFinishedStrokeColor());
bundle.putInt(INSTANCE_UNFINISHED_STROKE_COLOR, getUnfinishedStrokeColor());
bundle.putFloat(INSTANCE_ARC_ANGLE, getArcAngle());
bundle.putString(INSTANCE_SUFFIX, getSuffixText());
return bundle;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
if(state instanceof Bundle) {
final Bundle bundle = (Bundle) state;
strokeWidth = bundle.getFloat(INSTANCE_STROKE_WIDTH);
suffixTextSize = bundle.getFloat(INSTANCE_SUFFIX_TEXT_SIZE);
suffixTextPadding = bundle.getFloat(INSTANCE_SUFFIX_TEXT_PADDING);
bottomTextSize = bundle.getFloat(INSTANCE_BOTTOM_TEXT_SIZE);
bottomText = bundle.getString(INSTANCE_BOTTOM_TEXT);
textSize = bundle.getFloat(INSTANCE_TEXT_SIZE);
textColor = bundle.getInt(INSTANCE_TEXT_COLOR);
setMax(bundle.getInt(INSTANCE_MAX));
setProgress(bundle.getInt(INSTANCE_PROGRESS));
finishedStrokeColor = bundle.getInt(INSTANCE_FINISHED_STROKE_COLOR);
unfinishedStrokeColor = bundle.getInt(INSTANCE_UNFINISHED_STROKE_COLOR);
suffixText = bundle.getString(INSTANCE_SUFFIX);
initPainters();
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE));
return;
}
super.onRestoreInstanceState(state);
}
}
I want to increase radius of arc and increase circumference of it .
Any hep wil be appreciated .
Thanx in advance :)

I want to increase radius of arc and increase circumference of it
Accordingly to the code you posted, the size is decide during onMeasure
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
rectF.set(strokeWidth / 2f, strokeWidth / 2f, width - strokeWidth / 2f, MeasureSpec.getSize(heightMeasureSpec) - strokeWidth / 2f);
float radius = width / 2f;
float angle = (360 - arcAngle) / 2f;
arcBottomHeight = radius * (float) (1 - Math.cos(angle / 180 * Math.PI));
}
So, in order to increase the radius, you have to increase width and height your provide in the layout. If you want to change the arc's color you can provide statically, in the xml
arc_finished_color and arc_unfinished_color
E.g.
<com.androidhive.musicplayer.equalizer.ArcProgress
android:id="#+id/songProgressBar"
android:background="#214193"
android:layout_marginLeft="50dp"
android:layout_width="100dp"
android:layout_height="100dp"
custom:arc_progress="55"
custom:arc_bottom_text="MEMORY"
custom:arc_finished_color="#color/finished_color"
custom:arc_unfinished_color="#color/unfinished_color"/>

Related

AndroidRuntime: FATAL EXCEPTION: Nullpointerexception, Inflateexception

Please, i got many errors on my code really i need your help.
Errors:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: tools.myapp.app1, PID: 23986
java.lang.RuntimeException: Unable to start activity ComponentInfo{tools.myapp.app1/tools.myapp.app1.activitys.GreatingCardShowActivity}: android.view.InflateException: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Error inflating class tools.myapp.app1.StickerView.StickerView
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3479)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3651)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2104)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:7861)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
Caused by: android.view.InflateException: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Error inflating class tools.myapp.app1.StickerView.StickerView
Caused by: android.view.InflateException: Binary XML file line #58 in tools.myapp.app1:layout/activity_greating_card_show: Error inflating class tools.myapp.app1.StickerView.StickerView
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at android.view.LayoutInflater.createView(LayoutInflater.java:856)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1008)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:963)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1125)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1086)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1128)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1086)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1128)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1086)
at android.view.LayoutInflater.inflate(LayoutInflater.java:684)
at android.view.LayoutInflater.inflate(LayoutInflater.java:536)
at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
at `androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:706)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195)
at tools.myapp.app1.activitys.GreatingCardShowActivity.onCreate(GreatingCardShowActivity.java:1001)
at android.app.Activity.performCreate(Activity.java:8109)
at android.app.Activity.performCreate(Activity.java:8083)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3452)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3651)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2104)
at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime: at android.os.Looper.loop(Looper.java:236)
at android.app.ActivityThread.main(ActivityThread.java:7861)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.drawable.Drawable.getIntrinsicWidth()' on a null object reference
at tools.myapp.app1.StickerView.DrawableSticker.getWidth(DrawableSticker.java:38)
at tools.myapp.app1.StickerView.DrawableSticker.<init>(DrawableSticker.java:10)
at tools.myapp.app1.StickerView.BitmapStickerIcon.<init>(BitmapStickerIcon.java:16)
at tools.myapp.app1.StickerView.StickerView.<init>(StickerView.java:129)
at tools.myapp.app1.StickerView.StickerView.<init>(StickerView.java:111)
Here: layout/activity_greating_card_show
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background_ss">
code......
**//this is a line #58 that the compiler marked**
<tools.myapp.app1.StickerView.StickerView
android:id="#+id/stickerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:layout_margin="#dimen/_8sdp"
android:visibility="visible" />
</RelativeLayout>
Here: GreatingCardShowActivity/onCreate
public void onCreate(#Nullable Bundle bundle) {
ImageView imageView;
float f;
super.onCreate(bundle);
**//the compiler select this line #1001**
setContentView(R.layout.activity_greating_card_show);
InterstitialAdHelper instance = InterstitialAdHelper.Companion.getInstance();
if (instance == null) {
Intrinsics.throwNpe();
}
instance.load(this, this);
this.activity = this;
this.assetManager = getAssets();
this.mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
if (Share.ActivityCardCreate) {
this.bgposition = getIntent().getStringExtra("bgposition");
Log.e("val", "onCreate: bg pos-->" + this.bgposition);
} else {
Intent intent = getIntent();
this.gretingcatname = intent.getStringExtra("gretingcatname");
this.pos = intent.getIntExtra("pos", 0);
}
initView();
if (Share.ActivityCardCreate || Share.ActivityGalleryCardCreate) {
ImageView imageView2 = this.iv_custom_sticker_view;
if (imageView2 == null) {
Intrinsics.throwNpe();
}
f = 1.0f;
imageView2.setAlpha(1.0f);
ImageView imageView3 = this.iv_gc_quotes;
if (imageView3 == null) {
Intrinsics.throwNpe();
}
imageView3.setAlpha(1.0f);
imageView = this.iv_ad_frame;
} else {
ImageView imageView4 = this.iv_custom_sticker_view;
if (imageView4 == null) {
Intrinsics.throwNpe();
}
f = 0.5f;
imageView4.setAlpha(0.5f);
ImageView imageView5 = this.iv_gc_quotes;
if (imageView5 == null) {
Intrinsics.throwNpe();
}
imageView5.setAlpha(0.5f);
imageView = this.iv_ad_frame;
}
imageView.setAlpha(f);
initAction();
drawables_sticker.clear();
}
Here: class DrawableSticker
public class DrawableSticker extends Sticker {
private Drawable mDrawable;
**// Below is line #10 the compiler select getWidth() in this line**
private final Rect mRealBounds = new Rect(0, 0, getWidth(), getHeight());
public DrawableSticker(Drawable drawable) {
this.mDrawable = drawable;
this.a = new Matrix();
}
#Override
public void draw(Canvas canvas) {
canvas.save();
canvas.concat(this.a);
this.mDrawable.setBounds(this.mRealBounds);
this.mDrawable.draw(canvas);
canvas.restore();
}
#Override
public Drawable getDrawable() {
return this.mDrawable;
}
#Override
public int getHeight() {
return this.mDrawable.getIntrinsicHeight();
}
#Override
public int getWidth() {
return this.mDrawable.getIntrinsicWidth(); **//here line #38**
}
#Override
public void release() {
super.release();
if (this.mDrawable != null) {
this.mDrawable = null;
}
}
#Override
public void setDrawable(Drawable drawable) {
this.mDrawable = drawable;
}
}
This is : class Sticker
"extended in class DrawableSticker"
public abstract class Sticker {
protected Matrix a;
protected boolean b;
private String tag = "";
private float[] mMatrixValues = new float[9];
private float getMatrixAngle(#NonNull Matrix matrix) {
return (float) (-(Math.atan2((double) getMatrixValue(matrix, 1), (double)
getMatrixValue(matrix, 0)) * 57.29577951308232d));
}
private float getMatrixScale(#NonNull Matrix matrix) {
return (float) Math.sqrt(Math.pow((double) getMatrixValue(matrix, 0), 2.0d) +
Math.pow((double) getMatrixValue(matrix, 3), 2.0d));
}
private float getMatrixValue(#NonNull Matrix matrix, #IntRange(from = 0, to = 9) int i) {
matrix.getValues(this.mMatrixValues);
return this.mMatrixValues[i];
}
public boolean contains(float f, float f2) {
Matrix matrix = new Matrix();
matrix.setRotate(-getCurrentAngle());
float[] fArr = new float[8];
float[] fArr2 = new float[2];
matrix.mapPoints(fArr, getMappedBoundPoints());
matrix.mapPoints(fArr2, new float[]{f, f2});
return StickerUtils.trapToRect(fArr).contains(fArr2[0], fArr2[1]);
}
public abstract void draw(Canvas canvas);
public RectF getBound() {
return new RectF(0.0f, 0.0f, (float) getWidth(), (float) getHeight());
}
public float[] getBoundPoints() {
return !this.b ? new float[]{0.0f, 0.0f, (float) getWidth(), 0.0f, 0.0f, (float)
getHeight(), (float) getWidth(), (float) getHeight()} : new float[]{(float) getWidth(), 0.0f,
0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 0.0f, (float) getHeight()};
}
public PointF getCenterPoint() {
return new PointF((float) (getWidth() / 2), (float) (getHeight() / 2));
}
public float getCurrentAngle() {
return getMatrixAngle(this.a);
}
public float getCurrentHeight() {
return getMatrixScale(this.a) * ((float) getHeight());
}
public float getCurrentScale() {
return getMatrixScale(this.a);
}
public float getCurrentWidth() {
return getMatrixScale(this.a) * ((float) getWidth());
}
public abstract Drawable getDrawable();
public abstract int getHeight();
public RectF getMappedBound() {
RectF rectF = new RectF();
this.a.mapRect(rectF, getBound());
return rectF;
}
public float[] getMappedBoundPoints() {
float[] fArr = new float[8];
this.a.mapPoints(fArr, getBoundPoints());
return fArr;
}
public PointF getMappedCenterPoint() {
PointF centerPoint = getCenterPoint();
float[] mappedPoints = getMappedPoints(new float[]{centerPoint.x, centerPoint.y});
return new PointF(mappedPoints[0], mappedPoints[1]);
}
public float[] getMappedPoints(float[] fArr) {
float[] fArr2 = new float[fArr.length];
this.a.mapPoints(fArr2, fArr);
return fArr2;
}
public Matrix getMatrix() {
return this.a;
}
public abstract int getWidth();
public boolean isFlipped() {
return this.b;
}
public void release() {
}
public abstract void setDrawable(Drawable drawable);
public void setFlipped(boolean z) {
this.b = z;
}
public void setMatrix(Matrix matrix) {
this.a.set(matrix);
}
public void setTag(String str) {
this.tag = str;
}
}
And this is : class BitmapStickerIcon
public class BitmapStickerIcon extends DrawableSticker {
public static final float DEFAULT_ICON_EXTRA_RADIUS = 10.0f;
public static final float DEFAULT_ICON_RADIUS = 30.0f;
private float x;
private float y;
private float mIconRadius ;
private float mIconExtraRadius ;
public BitmapStickerIcon(Drawable drwbl) {
super(drwbl); **//this is line #16 selected by compiler**
this.mIconRadius = 30.0f;
this.mIconExtraRadius = 10.0f;
}
public void draw(Canvas canvas, Paint paint) {
canvas.drawCircle(this.x, this.y, this.mIconRadius, paint);
super.draw(canvas);
}
public float getIconExtraRadius() {
return this.mIconExtraRadius;
}
public float getIconRadius() {
return this.mIconRadius;
}
public float getX() {
return this.x;
}
public float getY() {
return this.y;
}
public void setIconExtraRadius(float f) {
this.mIconExtraRadius = f;
}
public void setIconRadius(float f) {
this.mIconRadius = f;
}
public void setX(float f) {
this.x = f;
}
public void setY(float f) {
this.y = f;
}
}
Here : class StickerView
public class StickerView extends FrameLayout {
public static final float MAX_SCALE_SIZE = 3.2f;
public static final float MIN_SCALE_SIZE = 0.1f;
private static final String TAG = "StickerView";
public static float[] bitmapPoints;
public static boolean mLocked;
public static List<Sticker> mStickers = new ArrayList();
private Paint mBorderPaint;
private ActionMode mCurrentMode;
private BitmapStickerIcon mDeleteIcon;
private Matrix mDownMatrix;
private float mDownX;
private float mDownY;
private BitmapStickerIcon mEditIcon;
private BitmapStickerIcon mFlipIcon;
private Sticker mHandlingSticker;
private PointF mMidPoint;
private Matrix mMoveMatrix;
private float mOldDistance;
private float mOldRotation;
private OnStickerOperationListener mOnStickerOperationListener;
private Matrix mSizeMatrix;
private RectF mStickerRect;
private int mTouchSlop;
private BitmapStickerIcon mZoomIcon;
public static class kcm1 {
static final int[] aaz;
static {
int[] iArr = new int[ActionMode.values().length];
aaz = iArr;
try {
iArr[ActionMode.NONE.ordinal()] = 1;
} catch (NoSuchFieldError unused) {
}
try {
aaz[ActionMode.DRAG.ordinal()] = 2;
} catch (NoSuchFieldError unused2) {
}
try {
aaz[ActionMode.ZOOM_WITH_TWO_FINGER.ordinal()] = 3;
} catch (NoSuchFieldError unused3) {
}
try {
aaz[ActionMode.ZOOM_WITH_ICON.ordinal()] = 4;
} catch (NoSuchFieldError unused4) {
}
}
}
public enum ActionMode {
NONE,
DRAG,
ZOOM_WITH_TWO_FINGER,
ZOOM_WITH_ICON,
DELETE,
FLIP_HORIZONTAL,
CLICK
}
public interface OnStickerOperationListener {
void onStickerClicked(Sticker sticker);
void onStickerDeleted(Sticker sticker);
void onStickerDragFinished(Sticker sticker);
void onStickerEdit(Sticker sticker);
void onStickerFlipped(Sticker sticker);
void onStickerZoomFinished(Sticker sticker);
}
public StickerView(Context context) {
this(context, null); **//this line #111 selected by compiler**
}
public StickerView(Context context, AttributeSet attributeSet) {
this(context, attributeSet, 0);
}
public StickerView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
this.mOldDistance = 0.0f;
this.mOldRotation = 0.0f;
this.mCurrentMode = ActionMode.NONE;
this.mTouchSlop = 3;
Paint paint = new Paint();
this.mBorderPaint = paint;
paint.setAntiAlias(true);
this.mBorderPaint.setColor(-16777216);
this.mBorderPaint.setAlpha(128);
this.mSizeMatrix = new Matrix();
this.mDownMatrix = new Matrix();
this.mMoveMatrix = new Matrix();
this.mStickerRect = new RectF();
**//Below line #129 the compiler select BitmapStickerIcon**
this.mDeleteIcon = new BitmapStickerIcon(ContextCompat.getDrawable(getContext(), R.drawable.ic_close_white_18dp));
this.mZoomIcon = new BitmapStickerIcon(ContextCompat.getDrawable(getContext(), R.drawable.ic_scale_white_18dp));
} ...more
I have no idea how to fix the errors, I have tested many solutions but nothing changed.
I will be happy for your help.
In the StickerView file:
Remove the StickerView(Context context) constructor
Put the initialization code also in the StickerView(Context context, AttributeSet attributeSet) constructor (creating a dedicated method is a good approach) and
Change this(context, attributeSet, 0) to super(context, attributeSet)
public StickerView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
setup();
}
public StickerView(Context context, AttributeSet attributeSet, int i) {
super(context, attributeSet, i);
setup();
}
private void setup() {
this.mOldDistance = 0.0f;
this.mOldRotation = 0.0f;
this.mCurrentMode = ActionMode.NONE;
this.mTouchSlop = 3;
Paint paint = new Paint();
this.mBorderPaint = paint;
paint.setAntiAlias(true);
this.mBorderPaint.setColor(-16777216);
this.mBorderPaint.setAlpha(128);
this.mSizeMatrix = new Matrix();
this.mDownMatrix = new Matrix();
this.mMoveMatrix = new Matrix();
this.mStickerRect = new RectF();
**//Below line #129 the compiler select BitmapStickerIcon**
this.mDeleteIcon = new BitmapStickerIcon(ContextCompat.getDrawable(getContext(), R.drawable.ic_close_white_18dp));
this.mZoomIcon = new BitmapStickerIcon(ContextCompat.getDrawable(getContext(), R.drawable.ic_scale_white_18dp));
}

How can achieve this custom view wave animation?

I'm trying to achieve this custom wave animation with circle in the middle of the wave.
Below is my custom view. It runs in a different direction and the draw has a line in the middle of the wave that results in a bad UX.
I try to follow some related tutorials but I cannot get the same animation.
If there is any library o code sample to follow it could help me a lot.
Thanks.
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.guille.stressmeterapp.R;
import org.jetbrains.annotations.Nullable;
public class WaveCustomView extends View {
private int mWidth = 0;
private int mHeight = 0;
private Path path;
private Paint paint;
private int waveHeight = 300;
private int waveWidth = 600;
private int originalY = 750;
private Region region;
private int dx = 0;
private Bitmap mBitmap;
private int animationDuration = 3000;
public WaveCustomView(Context context) {
super(context, null);
initUi();
}
public WaveCustomView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs, 0);
initUi();
}
public WaveCustomView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initUi();
}
private void initUi() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.parseColor("#000000"));
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(15);
path = new Path();
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.circle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
int desired = (int) (getPaddingLeft() + getPaddingRight());
width = desired;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
int desired = (int) (getPaddingTop() + getPaddingBottom());
height = desired;
}
mWidth = width;
mHeight = height;
waveWidth = mWidth / 2;
setMeasuredDimension(width, height);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, paint);
setDrawData();
Rect bounds = region.getBounds();
if (bounds.top < originalY) {
canvas.drawBitmap(mBitmap, bounds.right - (mBitmap.getWidth() >> 1), bounds.top - (mBitmap.getHeight() >> 1), paint);
} else {
canvas.drawBitmap(mBitmap, bounds.right - (mBitmap.getWidth() >> 1), bounds.bottom - (mBitmap.getHeight() >> 1), paint);
}
}
private void setDrawData() {
path.reset();
int halfWaveWidth = waveWidth / 2;
path.moveTo(-waveWidth + dx, originalY);
for (int i = -waveWidth; i < mWidth + waveWidth; i = i + waveWidth) {
path.rQuadTo(halfWaveWidth >> 1, -waveHeight, halfWaveWidth, 0);
path.rQuadTo(halfWaveWidth >> 1, waveHeight, halfWaveWidth, 0);
}
region = new Region();
Region clip = new Region((int) (mWidth / 2 - 0.1), 0, mWidth / 2, mHeight * 2);
region.setPath(path, clip);
path.close();
}
public void startAnimate() {
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float factor = (float) valueAnimator.getAnimatedValue();
dx = (int) ((waveWidth) * factor);
invalidate();
}
});
animator.setDuration(animationDuration);
animator.start();
}
Your code looks OK. Just remove this line from setDrawData method.
path.close();
This line closes path. It means it connect path begginnig with path end. That's why you see line in the middle of the wave.
Here is result without middle line:
If you want to change the direction of animation just change sign of dx variable. Change this:
dx = (int) ((waveWidth) * factor);
To this:
dx = - (int) (waveWidth * factor);
Or instead of this:
path.moveTo(-waveWidth + dx, originalY);
Do this:
path.moveTo(-waveWidth - dx, originalY);
Final result:

Custom view being drawn sometimes

I have a custom view, that is sometimes being drawn and sometimes not .. this is reproduce-able across multiple phone.
Don't know why this is happening .. setDimensions() is being called during the onMeasure call of a GalleryGridElement (relative layout) which I use as gallery elements in my recyclerview.
One example would be .. going into the recycler view gallery activity, the circular progress view is there .. when you leave the activity and come back .. onResume creates a new adapter and gives it to the recycler view .. however the circular progress views don't show this time:
public class CircularProgressView extends View {
private Paint mIndicatorColour;
private RectF mIndicatorRect;
private Paint mBackCircleColour;
private static final float START_ANGLE = -90;
private volatile float mStopAngle = 0;
private float mOutterCircleStrokeWidth = 20;
private float mInnerCircleStrokeWidth = 16;
private float mViewWidth = 0, mViewHeight = 0;
private volatile int mCurrentProgress = 0;
private ExecutorService mExecutorService;
public CircularProgressView(Context context) {
super(context);
setUp();
}
public CircularProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
setUp();
}
public CircularProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setUp();
}
private void setUp(){
mIndicatorRect = new RectF(0,0,300,300);
mIndicatorColour = new Paint();
mIndicatorColour.setColor(Color.parseColor("#D62F85"));
mIndicatorColour.setStyle(Paint.Style.STROKE);
mIndicatorColour.setStrokeWidth(mInnerCircleStrokeWidth);
mIndicatorColour.setAntiAlias(true);
mIndicatorColour.setDither(true);
mIndicatorColour.setStrokeJoin(Paint.Join.ROUND);
mIndicatorColour.setStrokeCap(Paint.Cap.ROUND);
mBackCircleColour = new Paint();
mBackCircleColour.setColor(Color.WHITE);
mBackCircleColour.setStyle(Paint.Style.STROKE);
mBackCircleColour.setStrokeWidth(mOutterCircleStrokeWidth);
mBackCircleColour.setAntiAlias(true);
mBackCircleColour.setDither(true);
mBackCircleColour.setStrokeJoin(Paint.Join.ROUND);
mBackCircleColour.setStrokeCap(Paint.Cap.ROUND);
mExecutorService = Executors.newSingleThreadExecutor();
}
public void setDimensions(float width, int scaleCircleThicknessValue){
mViewHeight = width;
mViewWidth = width;
mIndicatorRect.left = mIndicatorRect.top = mOutterCircleStrokeWidth;
mIndicatorRect.right = mIndicatorRect.bottom = width - mOutterCircleStrokeWidth;
mIndicatorColour.setStrokeWidth(mInnerCircleStrokeWidth);
mBackCircleColour.setStrokeWidth(mOutterCircleStrokeWidth);
mInnerCircleStrokeWidth = (0.1f * scaleCircleThicknessValue) * width;
mOutterCircleStrokeWidth = mInnerCircleStrokeWidth + 5;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int desiredWidth = Math.round(mViewWidth);
int desiredHeight = Math.round(mViewHeight);
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;
}
//Set values
setMeasuredDimension(width, height);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(mIndicatorRect, 0, 360, false, mBackCircleColour);
canvas.drawArc(mIndicatorRect, START_ANGLE, mStopAngle, false, mIndicatorColour);
}
public synchronized void setProgress(final int progress) {
if ((mCurrentProgress != progress) && (progress > 0)) {
mCurrentProgress = progress;
mExecutorService.submit(new Runnable() {
#Override
public void run() {
final float currentAngle = mStopAngle;
float newAngle = (360f * ((float) progress / 100f));
float step = (Math.round(newAngle) - Math.round(currentAngle)) <= 1 ? 1 : (newAngle - currentAngle)/5f;
if (step < 0.01) {
newAngle = 359;
}
for (float i = currentAngle; i < newAngle; i += step) {
try {
mStopAngle = i;
postInvalidate();
Thread.sleep(1000 / 60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
}
public float getProgress(){
return (360f-mStopAngle) < 1f ? 1 : mStopAngle / 360f;
}
}
Just following up on this incase someone runs into this issue:
Since I am using a custom view inside a custom view with the recycler view.
When I bind the view-holder to model, I make sure to completely re-render the view ... ie :
mCircularProgressView.setVisibility(VISIBLE);
mCircularProgressView.setDimensions(getWidth() * 0.82f, 1);
mCircularProgressView.requestLayout();
mCircularProgressView.postInvalidate();
This makes sure the view is drawn no matter what.

Unable to properly add custom views on click at x,y position in relative layout

i have an issue with inserting custom views into my relative layout that takes only a part of the screen. When the activity loads it should populate views with specific width and height at x,y position that i get from my server, then when i click insert mode and click on the relative layout it should draw the view where i clicked as well...The problem is, sometimes it draws rectangle(should be square), sometimes just a line, sometimes nothing. It behaves differently if i change my width and height.
Custom view :
public class TableView extends View {
private static final String TAG = "TableView";
private int numberOfSeats;
private int tableId;
private int positionX;
private int positionY;
private int objectWidth;
private int objectHeight;
private boolean isTaken;
private String tableKind;
private Rect rectangle;
private Paint paint;
/* public TableView(Context context, AttributeSet attrs) {
super(context, attrs);
}*/
public TableView(Context context,int numberOfSeats,int tableId,int positionX,int positionY,int width,int height
,boolean isTaken, String tableKind) {
super(context);
this.numberOfSeats = numberOfSeats;
this.tableId = tableId;
this.positionX = positionX;
this.positionY = positionY;
this.objectWidth = width;
this.objectHeight = height;
this.isTaken = isTaken;
this.tableId = tableId;
this.tableKind = tableKind;
//defining shape
rectangle = new Rect(positionX,positionY,width,height);
//defining shape color
paint = new Paint();
paint.setColor(Color.GRAY);
Log.i(TAG, "TableView: tableId: "+tableId+" isTaken: "+isTaken);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = objectWidth;
int desiredHeight = objectHeight;
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);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//canvas.drawColor(Color.BLUE);
canvas.drawRect(rectangle, paint);
}
public int getNumberOfSeats() {
return numberOfSeats;
}
public int getTableId() {
return tableId;
}
public int getPositionX() {
return positionX;
}
public int getPositionY() {
return positionY;
}
public int getObjectWidth() {
return objectWidth;
}
public int getObjectHeight() {
return objectHeight;
}
public boolean isTaken() {
return isTaken;
}
public String getTableKind() {
return tableKind;
}
}
Main activity:
public class MainActivity extends AppCompatActivity {
int numberOfSeats = 1;
int tableId = 0;
int positionX = 100;
int positionY = 208;
boolean isTaken = true;
String tableKind = "table";
int objectWidth =200;
int objectHeight=200;
TextView topTable;
RelativeLayout floorPlan ;
Button saveBtn ;
private boolean insertTableCheck = false;
private static final String TAG = "MainActivity";
private int idTest = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
topTable =(TextView) findViewById(R.id.tableView);
floorPlan = (RelativeLayout) findViewById(R.id.floor_plan);
saveBtn = (Button) findViewById(R.id.saveBtn);
for (int i = 0;i<15;i++) {
TableView tv = new TableView(MainActivity.this, numberOfSeats, tableId, positionX, positionY, objectWidth, objectHeight
, isTaken, tableKind);
tv.setTag(i);
positionX +=25;
positionY +=34;
//tv.setY(positionY);
//tv.setX(positionX);
floorPlan.addView(tv);
}
floorPlan.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (insertTableCheck) {
saveBtn.setVisibility(View.VISIBLE);
int x = (int)motionEvent.getX()-objectWidth/2;
int y =(int) motionEvent.getY()-objectHeight/2;
Log.i(TAG, "insertTable: insertingTable on: " + x + " " + y);
TableView tav = new TableView(MainActivity.this,numberOfSeats,tableId,x,
y,objectWidth,objectHeight,isTaken,tableKind);
tav.setX(x);
tav.setY(y);
floorPlan.addView(tav);
/*TextView tableForInsert = new TextView(MainActivity.this);
tableForInsert.setBackgroundColor(Color.BLACK);
tableForInsert.setWidth(objectWidth);
tableForInsert.setHeight(objectHeight);
tableForInsert.setX(x);
tableForInsert.setY(y);
floorPlan.addView(tableForInsert);*/
insertTableCheck = false;
} else {
Log.i(TAG, "onTouch: just clicked on layout");
}
return true;
}
});
}
Note that for loop and the data above is just for testing! Any help would be much appreciated. Thanks

How to implement zoom & pan in Libgdx Java?

I would like to add a zoom and pan mechanic to my game but everything I have looked up on the web has been complete and utter failure.
If you could give me a good example of implementing these functions that would be sweet.
Here is the class I'm trying to get it to work in.
package com.adam.finis.screens;
import com.adam.finis.Main;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
public class Play extends ApplicationAdapter implements Screen, GestureListener, ApplicationListener{
//Core Variables
private Main game;
public static InputMultiplexer inputMultiPlex;
//Texture Variables
Texture Title;
private TmxMapLoader mapLoader;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
//Sprite Variables
public static boolean spawnSprite = false;
//Font
private BitmapFont font;
//Window Variables
private OrthographicCamera gameCam;
private Viewport gamePort;
private PlayHud hudPlay;
private int mapX = 1952;
private int mapY = 1952;
private int mapHalfX = mapX / 2;
private int mapHalfY = mapY / 2;
public static boolean GAME_PAUSED = false;
//Random Variables
private Vector2 dragOld, dragNew;
public static Vector2 worldSize;
//DEBUG
private String message;
private Texture debugTexture;
private Sprite debugSprite;
public Play(Main game){
this.game = game;
gameCam = new OrthographicCamera();
gameCam.setToOrtho(false, Main.V_WIDTH, Main.V_HEIGHT);
gamePort = new FitViewport(Main.V_WIDTH, Main.V_HEIGHT, gameCam);
hudPlay = new PlayHud(game.sb);
mapLoader = new TmxMapLoader();
map = mapLoader.load("images/level1.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
gameCam.position.set(mapHalfX, mapHalfY, 0);
GestureDetector gd = new GestureDetector(this);
inputMultiPlex = new InputMultiplexer();
inputMultiPlex.addProcessor(hudPlay.stage);
inputMultiPlex.addProcessor(hudPlay.debugStage);
inputMultiPlex.addProcessor(gd);
Gdx.input.setInputProcessor(gd);
debugTexture = new Texture(Gdx.files.internal("images/house.png"));
debugSprite = new Sprite(debugTexture);
worldSize = new Vector2(mapX, mapY);
font = new BitmapFont(Gdx.files.internal("fonts/lemonMilk.fnt"),false);
font.setColor(Color.RED);
}
#Override
public void show() {
}
public void handleInput(float dt){
//Keyboard Settings
if (Gdx.input.isKeyPressed(Input.Keys.W)) {
gameCam.position.y += 350 * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.A)) {
gameCam.position.x -= 350 * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.S)) {
gameCam.position.y -= 350 * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.D)) {
gameCam.position.x += 350 * dt;
}
//ZOOM
if (Gdx.input.isKeyPressed(Input.Keys.O)) {
gameCam.zoom += 1.5f * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.P)) {
gameCam.zoom -= 1.5f * dt;
}
//CAMERA BOUNDS
gameCam.zoom = MathUtils.clamp(gameCam.zoom, 0.1f, mapX / gameCam.viewportWidth);
//|
float camX = gameCam.position.x;
float camY = gameCam.position.y;
//|
Vector2 camMin = new Vector2(gameCam.viewportWidth, gameCam.viewportHeight);
Vector2 camMax = new Vector2(1952, 1952);
//|
camMin.scl(gameCam.zoom/2);
camMax.sub(camMin);
//|
camX = Math.min(camMax.x, Math.max(camX, camMin.x));
camY = Math.min(camMax.y, Math.max(camY, camMin.y));
gameCam.position.set(camX, camY, gameCam.position.z);
//------------------------------------------------------------------------------------
//Touch Settings
if (Gdx.input.justTouched()){
dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
dragOld = dragNew;
}
if (Gdx.input.isTouched()){
dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
if (!dragNew.equals(dragOld)){
gameCam.translate(dragOld.x - dragNew.x, dragNew.y - dragOld.y);
dragOld = dragNew;
}
}
}
public void update(float dt){
handleInput(dt);
gameCam.update();
renderer.setView(gameCam);
}
#Override
public void render(float delta) {
if(GAME_PAUSED == false){
update(delta);
//CLEAR SCREEN - BLACK
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//INIT ALL INPUT
Gdx.input.setInputProcessor(inputMultiPlex);
//RENDER MAP
renderer.setView(gameCam);
renderer.render();
//DRAW
if(spawnSprite == true){
game.sb.begin();
game.sb.draw(debugSprite, 1500, 500);
game.sb.end();
}
//DRAW HUD
hudPlay.stage.getViewport().apply();
hudPlay.stage.act();
hudPlay.stage.draw();
//debug DRAW HUD
hudPlay.debugStage.getViewport().apply();
hudPlay.debugStage.act();
hudPlay.debugStage.draw();
//PROJECTION
game.sb.setProjectionMatrix(gameCam.combined);
game.hudSb.setProjectionMatrix(hudPlay.debugStage.getCamera().combined);
game.hudSb.setProjectionMatrix(hudPlay.stage.getCamera().combined);
if(Main.zoomOut == true){
gameCam.zoom += 1.5f * delta;
}
if(Main.zoomIn == true){
gameCam.zoom -= 1.5f * delta;
}
}
if(GAME_PAUSED == true){
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.input.setInputProcessor(inputMultiPlex);
game.sb.setProjectionMatrix(hudPlay.debugStage.getCamera().combined);
hudPlay.debugStage.getViewport().apply();
hudPlay.debugStage.act();
hudPlay.debugStage.draw();
}
}
#Override
public void resize(int width, int height) {
gamePort.update(width, height);
gameCam.viewportWidth = width/5f; //We will see width/32f units!
gameCam.viewportHeight = gameCam.viewportWidth * height/width;
hudPlay.stage.getViewport().update(width, height, true);
hudPlay.debugStage.getViewport().update(width, height, true);
}
#Override
public void pause() {}
#Override
public void resume() {}
#Override
public void hide() {}
#Override
public void dispose() {
game.sb.dispose();
renderer.dispose();
hudPlay.dispose();
font.dispose();
}
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
return false;
}
#Override
public boolean tap(float x, float y, int count, int button) {
message = "TAP";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean longPress(float x, float y) {
message = "LONG PRESS";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean fling(float velocityX, float velocityY, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "PAN";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
message = "Zoom performed";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2,
Vector2 pointer1, Vector2 pointer2) {
message = "Pinch performed";
Gdx.app.log("INFO", message);
return true;
}
}
Your own answer is right, but here is an improved version where zooming a second time is performed upon the previous zoom.
Also, camera translation speed is proportional to the current camera zoom.
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "PAN";
Gdx.app.log("INFO", message);
gameCam.translate(-deltaX * currentZoom,deltaY * currentZoom);
gameCam.update();
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
message = "Zoom performed";
Gdx.app.log("INFO", message);
gameCam.zoom = (initialDistance / distance) * currentZoom;
gameCam.update();
return true;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
Gdx.app.log("INFO", "panStop");
currentZoom = gameCam.zoom;
return false;
}
I fixed the issue sorry im new to all of this and its making me think a little too much.
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "PAN";
Gdx.app.log("INFO", message);
gameCam.translate(-deltaX, deltaY);
gameCam.update();
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
message = "Zoom performed";
Gdx.app.log("INFO", message);
gameCam.zoom = (initialDistance / distance) * ZOOM;
gameCam.update();
return true;
}

Categories