I am trying to implement the spinning activity similar to the the one I have placed below in Android. I believe I should use the ProgressDialog. My issue arises from how to actually manipulate the ProgressDialog to appear like the activity indicator.
Any thoughts are welcome. A link to an example would even be better.
Thanks.
REEDIT:
myProgress.java
public class myProgress extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ProgressDialog d = (ProgressDialog)findViewById(R.id.progres);
main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/progres"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
>
<ProgressBar
android:id="#+id/progressBar"
android:indeterminate="true"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
</RelativeLayout>
I wrote my own custom LoadingIndicatorView.
It consists of two files:
LoadingIndicatorBarView
LoadingIndicatorView
Pros:
Programmatically created, no PNG antics meaning scalable and crisp :D
Customizable bar colors and corner radius (if you understand my code)
Cons:
Not as performant as the iOS version (I'm just a beginner Android developer coming from iOS background, what do you expect?) :P
Disclaimer:
Don't blame me if your project blows up, I'm putting this as free public domain code.
You'll notice my coding style and structure resemble my iOS programming codes a lot. I do everything programmatically, no XML if I can get away with it.
How to use this Loading Indicator
After you've copied and pasted all three class source codes into their Java file, you want to use the LoadingIndicatorView class, you shouldn't need to touch the other class, unless you want to customise the colour or rounded corner of each bar.
Create an instance of LoadingIndicatorView like this in your Activity:
import com.companyName.myApplication.views.LoadingIndicatorView;
public class MyActivity extends AppCompatActivity
{
public mainLayout RelativeLayout;
...
public LoadingIndicatorView loadingIndicator;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
initViews();
initLayouts();
addViews();
}
public void initViews()
{
mainLayout = new RelativeLayout(this);
mainLayout.setBackgroundColor(Color.BLACK);
...
// ---------------------------------------------------
// 40 here is the radius of the circle
// try and use multiples of 2, e.g. 40, 60, 80 etc
// ---------------------------------------------------
loadingIndicator = new LoadingIndicatorView(this, 40);
// hide until ready to start animating
loadingIndicator.setAlpha(0.0f);
}
public void initLayouts()
{
...
// Need API level 17 for this, set in your AndroidManifeset.xml
mainLayout.setId(View.generateViewId());
loadingIndicator.setId(View.generateViewId());
RelativeLayout.LayoutParams loadingIndicatorLayoutParams = new RelativeLayout.LayoutParams(
(int)(loadingIndicator.radius * 2.0f),
(int)(loadingIndicator.radius * 2.0f)
);
loadingIndicatorLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
loadingIndicator.setLayoutParams(loadingIndicatorLayoutParams);
}
public void addViews()
{
...
mainLayout.addView(loadingIndicator);
setContentView(mainLayout);
}
}
Once you're ready to show it, e.g. in a button click listener, then you call:
loadingIndicator.startAnimating();
When you want to stop and hide the indicator, call:
loadingIndicator.stopAnimating();
You end up with something like this:
LoadingIndicatorView.java
package com.companyName.myApplication.views;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.animation.RotateAnimation;
import android.widget.RelativeLayout;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by Zhang on 11/02/16.
*/
public class LoadingIndicatorView extends RelativeLayout
{
private Context context;
private int numberOfBars;
public ArrayList<LoadingIndicatorBarView> arrBars;
public float radius;
private boolean isAnimating;
private int currentFrame;
private final Handler handler = new Handler();
private Runnable playFrameRunnable;
public LoadingIndicatorView(Context context, float radius)
{
super(context);
this.context = context;
this.radius = radius;
this.numberOfBars = 12;
initViews();
initLayouts();
addViews();
spreadBars();
}
public void initViews()
{
arrBars = new ArrayList<LoadingIndicatorBarView>();
for(int i = 0; i < numberOfBars; i++)
{
LoadingIndicatorBarView bar = new LoadingIndicatorBarView(context, radius / 10.0f);
arrBars.add(bar);
}
}
public void initLayouts()
{
for(int i = 0; i < numberOfBars; i++)
{
LoadingIndicatorBarView bar = arrBars.get(i);
bar.setId(View.generateViewId());
RelativeLayout.LayoutParams barLayoutParams = new RelativeLayout.LayoutParams(
(int)(radius / 5.0f),
(int)(radius / 2.0f)
);
barLayoutParams.addRule(ALIGN_PARENT_TOP);
barLayoutParams.addRule(CENTER_HORIZONTAL);
bar.setLayoutParams(barLayoutParams);
}
}
public void addViews()
{
for(int i = 0; i < numberOfBars; i++)
{
LoadingIndicatorBarView bar = arrBars.get(i);
addView(bar);
}
}
public void spreadBars()
{
int degrees = 0;
for(int i = 0; i < arrBars.size(); i++)
{
LoadingIndicatorBarView bar = arrBars.get(i);
rotateBar(bar, degrees);
degrees += 30;
}
}
private void rotateBar(LoadingIndicatorBarView bar, float degrees)
{
RotateAnimation animation = new RotateAnimation(0, degrees, radius / 10.0f, radius);
animation.setDuration(0);
animation.setFillAfter(true);
bar.setAnimation(animation);
animation.start();
}
public void startAnimating()
{
setAlpha(1.0f);
isAnimating = true;
playFrameRunnable = new Runnable()
{
#Override
public void run()
{
playFrame();
}
};
// recursive function until isAnimating is false
playFrame();
}
public void stopAnimating()
{
isAnimating = false;
setAlpha(0.0f);
invalidate();
playFrameRunnable = null;
}
private void playFrame()
{
if(isAnimating)
{
resetAllBarAlpha();
updateFrame();
handler.postDelayed(playFrameRunnable, 0);
}
}
private void updateFrame()
{
if (isAnimating)
{
showFrame(currentFrame);
currentFrame += 1;
if (currentFrame > 11)
{
currentFrame = 0;
}
}
}
private void resetAllBarAlpha()
{
LoadingIndicatorBarView bar = null;
for (int i = 0; i < arrBars.size(); i++)
{
bar = arrBars.get(i);
bar.setAlpha(0.5f);
}
}
private void showFrame(int frameNumber)
{
int[] indexes = getFrameIndexesForFrameNumber(frameNumber);
gradientColorBarSets(indexes);
}
private int[] getFrameIndexesForFrameNumber(int frameNumber)
{
if(frameNumber == 0)
{
return indexesFromNumbers(0, 11, 10, 9);
}
else if(frameNumber == 1)
{
return indexesFromNumbers(1, 0, 11, 10);
}
else if(frameNumber == 2)
{
return indexesFromNumbers(2, 1, 0, 11);
}
else if(frameNumber == 3)
{
return indexesFromNumbers(3, 2, 1, 0);
}
else if(frameNumber == 4)
{
return indexesFromNumbers(4, 3, 2, 1);
}
else if(frameNumber == 5)
{
return indexesFromNumbers(5, 4, 3, 2);
}
else if(frameNumber == 6)
{
return indexesFromNumbers(6, 5, 4, 3);
}
else if(frameNumber == 7)
{
return indexesFromNumbers(7, 6, 5, 4);
}
else if(frameNumber == 8)
{
return indexesFromNumbers(8, 7, 6, 5);
}
else if(frameNumber == 9)
{
return indexesFromNumbers(9, 8, 7, 6);
}
else if(frameNumber == 10)
{
return indexesFromNumbers(10, 9, 8, 7);
}
else
{
return indexesFromNumbers(11, 10, 9, 8);
}
}
private int[] indexesFromNumbers(int i1, int i2, int i3, int i4)
{
int[] indexes = {i1, i2, i3, i4};
return indexes;
}
private void gradientColorBarSets(int[] indexes)
{
float alpha = 1.0f;
LoadingIndicatorBarView barView = null;
for(int i = 0; i < indexes.length; i++)
{
int barIndex = indexes[i];
barView = arrBars.get(barIndex);
barView.setAlpha(alpha);
alpha -= 0.125f;
}
invalidate();
}
}
LoadingIndicatorBarView.java
package com.companyName.myApplication.views;
import android.content.Context;
import android.graphics.Color;
import android.widget.RelativeLayout;
import com.companyName.myApplication.helper_classes.ToolBox;
/**
* Created by Zhang on 11/02/16.
*/
public class LoadingIndicatorBarView extends RelativeLayout
{
private Context context;
private float cornerRadius;
public LoadingIndicatorBarView(Context context, float cornerRadius)
{
super(context);
this.context = context;
this.cornerRadius = cornerRadius;
initViews();
}
public void initViews()
{
setBackground(ToolBox.roundedCornerRectWithColor(
Color.argb(255, 255, 255, 255), cornerRadius));
setAlpha(0.5f);
}
public void resetColor()
{
setBackground(ToolBox.roundedCornerRectWithColor(
Color.argb(255, 255, 255, 255), cornerRadius));
setAlpha(0.5f);
}
}
Toolbox.java
package com.companyName.myApplication.helper_classes;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Paint;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
/**
* Created by Zhang on 3/02/16.
*/
public class ToolBox
{
private static ToolBox instance;
public Context context;
private ToolBox()
{
}
public synchronized static ToolBox getInstance()
{
if(instance == null)
{
instance = new ToolBox();
}
return instance;
}
public static ShapeDrawable roundedCornerRectOutlineWithColor(int color, float cornerRadius,
float strokeWidth)
{
float[] radii = new float[] {
cornerRadius, cornerRadius,
cornerRadius, cornerRadius,
cornerRadius, cornerRadius,
cornerRadius, cornerRadius
};
RoundRectShape roundedCornerShape = new RoundRectShape(radii, null, null);
ShapeDrawable shape = new ShapeDrawable();
shape.getPaint().setColor(color);
shape.setShape(roundedCornerShape);
shape.getPaint().setStrokeWidth(strokeWidth);
shape.getPaint().setStyle(Paint.Style.STROKE);
return shape;
}
public static ShapeDrawable roundedCornerRectWithColor(int color, float cornerRadius)
{
float[] radii = new float[] {
cornerRadius, cornerRadius,
cornerRadius, cornerRadius,
cornerRadius, cornerRadius,
cornerRadius, cornerRadius
};
RoundRectShape roundedCornerShape = new RoundRectShape(radii, null, null);
ShapeDrawable shape = new ShapeDrawable();
shape.getPaint().setColor(color);
shape.setShape(roundedCornerShape);
return shape;
}
public static ShapeDrawable roundedCornerRectWithColor(int color, float topLeftRadius, float
topRightRadius, float bottomRightRadius, float bottomLeftRadius)
{
float[] radii = new float[] {
topLeftRadius, topLeftRadius,
topRightRadius, topRightRadius,
bottomRightRadius, bottomRightRadius,
bottomLeftRadius, bottomLeftRadius
};
RoundRectShape roundedCornerShape = new RoundRectShape(radii, null, null);
ShapeDrawable shape = new ShapeDrawable();
shape.getPaint().setColor(color);
shape.setShape(roundedCornerShape);
return shape;
}
public static int getScreenWidth()
{
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
public static int getScreenHeight()
{
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
public static int getScreenOrientation(Context context)
{
return context.getResources().getConfiguration().orientation;
}
public static boolean isLandscapeOrientation(Context context)
{
return getScreenOrientation(context) == Configuration.ORIENTATION_LANDSCAPE;
}
}
This Toolbox class is my convenience helper class to create rounded corner shapes etc in all my projects.
Hope that helps :D
this is how i achieve it
here is the code
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_LOADING:
final Dialog dialog = new Dialog(this, android.R.style.Theme_Translucent);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.loading);
dialog.setCancelable(true);
dialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
//onBackPressed();
}
});
return dialog;
default:
return null;
}
};
here is the loading.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/progres"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
>
<ProgressBar
android:indeterminate="true"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
</RelativeLayout>
call the dialog with
showDialog(DIALOG_LOADING);
hide it using
dismissDialog(DIALOG_LOADING);
UPDATE
if you want and custom indicator you can do the following in the layout.xml.
replace the ProgressBar with an ImageView
set the background of the ImageView to a AnimationDrawable
you can start the animation in onPrepareDialog
You are looking for progressDialog i believe. This link can you set you start with it.
http://www.helloandroid.com/tutorials/using-threads-and-progressdialog
pd = ProgressDialog.show(this, "Working..", "Calculating Pi", true,
false);
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
pd.dismiss();
tv.setText(pi_string);
}
};
Just look at this library. IOSDialog/Spinner library
It is very easy to use and solves your problem. With it, you can easily create and use spinner like in IOS.
The example of code:
final IOSDialog dialog1 = new IOSDialog.Builder(IOSDialogActivity.this)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
dialog0.show();
}
})
.setDimAmount(3)
.setSpinnerColorRes(R.color.colorGreen)
.setMessageColorRes(R.color.colorAccent)
.setTitle(R.string.standard_title)
.setTitleColorRes(R.color.colorPrimary)
.setMessageContent("My message")
.setCancelable(true)
.setMessageContentGravity(Gravity.END)
.build();
Result
final IOSDialog dialog0 = new IOSDialog.Builder(IOSDialogActivity.this)
.setTitle("Default IOS bar")
.setTitleColorRes(R.color.gray)
.build();
Result: stadard IOS Dialog
Related
I'm trying to make small App. This App have Activity, Custom View Class, and service.
1) Activity ask service for new Data and redraw Custom view
2) Service is listning to Bluetooth device and parse data.
Everything was fine, but I noticed that App is slowing down after 40 mins working.
I made another project remove service and find that it slowing too! So problem is my Customview class, maybe i have memory leaks in service to... but i have problem with drawings 100%.
I found that i have some objects that i'm creating on onDraw() method.. i try to move all thise staff to onSizeChanged() - but get more lags.
And now i need help. I need some example with simple drawings that depends on device width and height (I think my method is wrong - i use proportions of my 'Design' to calculate demetions in px)
By the way i'm using animator which make animations more smooth))
public class Dynamics {
/**
* Used to compare floats, if the difference is smaller than this, they are
* considered equal
*/
private static final float TOLERANCE = 0.01f;
/** The position the dynamics should to be at */
private float targetPosition;
/** The current position of the dynamics */
private float position;
/** The current velocity of the dynamics */
private float velocity;
/** The time the last update happened */
private long lastTime;
/** The amount of springiness that the dynamics has */
private float springiness;
/** The damping that the dynamics has */
private double damping;
public Dynamics(float springiness, float dampingRatio) {
this.springiness = springiness;
this.damping = dampingRatio * 2 * Math.sqrt(springiness);
}
public void setPosition(float position, long now) {
this.position = position;
lastTime = now;
}
public void setVelocity(float velocity, long now) {
this.velocity = velocity;
lastTime = now;
}
public void setTargetPosition(float targetPosition, long now) {
this.targetPosition = targetPosition;
lastTime = now;
}
public void update(long now) {
float dt = Math.min(now - lastTime, 50) / 1000f;
float x = position - targetPosition;
double acceleration = -springiness * x - damping * velocity;
velocity += acceleration * dt;
position += velocity * dt;
lastTime = now;
}
public boolean isAtRest() {
final boolean standingStill = Math.abs(velocity) < TOLERANCE;
final boolean isAtTarget = (targetPosition - position) < TOLERANCE;
return standingStill && isAtTarget;
}
public float getPosition() {
return position;
}
public float getTargetPos() {
return targetPosition;
}
public float getVelocity() {
return velocity;
}
}
In my Custom view i have this to set new data:
public void SetData(int[] NewData2,float[]newDatapoints)
{
this.NewData=NewData2;
long now = AnimationUtils.currentAnimationTimeMillis();
if (datapoints == null || datapoints.length != newDatapoints.length) {
datapoints = new Dynamics[newDatapoints.length];
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i] = new Dynamics(70f, 0.50f);
datapoints[i].setPosition(newDatapoints[i], now);
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
invalidate();
} else {
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
removeCallbacks(animator);
post(animator);
}
LastData=NewData;
//redraw();
}
Thise is "code" of my custom view, after all changes it's look terible, so i cut 90% of it. And i make some test code insted:
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.AnimationUtils;
import java.io.IOException;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Random;
public class CustomDisplayView extends View {
//paint for drawing custom view
private Paint RectPaint = new Paint();
//Динамические данные float
private Dynamics[] datapoints;
//Динамические статические Int
private int[] NewData = new int[500];
//созадем новый объект квадрат
private RectF rectf= new RectF();
//Задаем массив динамических цветов
int[] CurColors= new int[100];
int[] TargetColors= new int[100];
public CustomDisplayView(Context context, AttributeSet attrs){
super(context, attrs);
//Установка парметров красок
RectPaint.setAntiAlias(true);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != 0 && h != 0) {
//create Bitmap here
}
}
/**
* Override the onDraw method to specify custom view appearance using canvas
*/
#Override
protected void onDraw(Canvas canvas) {
//Get Screen size
//int viewWidth=this.getMeasuredWidth();
// int viewHeight = this.getMeasuredHeight();
//Выводим код цвета
RectPaint.setColor(0xff000000);
RectPaint.setTextSize(40);
canvas.restore();
canvas.drawText("V: " + datapoints[1].getPosition(), 20, 60, RectPaint);
//int saveCount = canvas.save();
for(int a=0;a<1000;a++)
{
rectf.set(datapoints[a].getPosition(), datapoints[a + 1].getPosition(), datapoints[a].getPosition() + datapoints[a + 1].getPosition() / 10, datapoints[a + 1].getPosition() + datapoints[a + 1].getPosition() / 10);
RectPaint.setColor(0x88005020);
//RectPaint.setColor(CurColor[a]);
//canvas.rotate(datapoints[1].getPosition(), viewWidth/2, viewHeight/2);
canvas.drawRoundRect(rectf, 0, 0, RectPaint);
//canvas.restore();
}
//canvas.restoreToCount(saveCount);
/*
for(int a=0;a<999;a++)
{
CurColors[a]=progressiveColor(CurColors[a], TargetColors[a], 2);
if(CurColors[a]==TargetColors[a])
{
TargetColors[a]=randomColor();
}
}
*/
canvas.restore();
}
//Рандом колор
public static int randomColor(){
Random random = new Random();
int[] ColorParams= new int[4];
ColorParams[0]=random.nextInt(235)+20;
ColorParams[1]=random.nextInt(255);
ColorParams[2]=random.nextInt(255);
ColorParams[3]=random.nextInt(255);
return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);
}
//Интерполяция цвета
public static int progressiveColor(int CurColor,int TargetColor,int Step){
//Current color
int[] ColorParams= new int[4];
ColorParams[0]=(CurColor >> 24) & 0xFF;
ColorParams[1]=(CurColor >> 16) & 0xFF;
ColorParams[2]=(CurColor >> 8) & 0xFF;
ColorParams[3]=CurColor & 0xFF;
//TargetColor
int[] TargetColorParams= new int[4];
TargetColorParams[0]=(TargetColor >> 24) & 0xFF;
TargetColorParams[1]=(TargetColor >> 16) & 0xFF;
TargetColorParams[2]=(TargetColor >> 8) & 0xFF;
TargetColorParams[3]=TargetColor & 0xFF;
for(int i=0;i<4;i++)
{
if(ColorParams[i]<TargetColorParams[i])
{
ColorParams[i]+=Step;
if(ColorParams[i]>TargetColorParams[i])
{
ColorParams[i]=TargetColorParams[i];
}
}
else if(ColorParams[i]>TargetColorParams[i])
{
ColorParams[i]-=Step;
if(ColorParams[i]<TargetColorParams[i])
{
ColorParams[i]=TargetColorParams[i];
}
}
}
//int red = r - (int)((float)(r*255)/(float)all);
//int green = (int)((float)(g*255)/(float)all);
return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);
//return String.format("#%06X", (0xFFFFFF & Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3])));
//return " "+opacity+" "+red+" "+green+" "+blue;
}
//each custom attribute should have a get and set method
//this allows updating these properties in Java
//we call these in the main Activity class
/**
* Get the current text label color
* #return color as an int
*/
public int getLabelColor(){
return 1;
}
/**
* Set the label color
* #param newColor new color as an int
*/
public void setLabelColor(int newColor){
//update the instance variable
//labelCol=newColor;
//redraw the view
invalidate();
requestLayout();
}
public void redraw(){
//redraw the view
invalidate();
requestLayout();
}
public void SetData(int[] NewData2,float[]newDatapoints)
{
this.NewData=NewData2;
long now = AnimationUtils.currentAnimationTimeMillis();
if (datapoints == null || datapoints.length != newDatapoints.length) {
datapoints = new Dynamics[newDatapoints.length];
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i] = new Dynamics(70f, 0.50f);
datapoints[i].setPosition(newDatapoints[i], now);
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
invalidate();
} else {
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
removeCallbacks(animator);
post(animator);
}
//redraw();
}
public int GetAction(float x,float y)
{
/*
if(x>(DicsCenterX-LineHalfSpeedZone) && x<(DicsCenterX+LineHalfSpeedZone) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
{
// private int SpeedZoneRadius2=0;
// private int PowerOutRadius=0;
//Смена режима
//начинаем смену размеру index / ms
ChangeVal(0,700);
return 1;
}
else if(x>(CofCantBGDrop*2) && x<(CofCantBGDrop*4) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
{
return 2;
}
else
{
return 0;
}
//return 0;
*/
return 1;
}
public static String fmt(double d)
{
double val = d/100;
String result;
if(val == (long) val)
result= String.format("%d",(long)d);
else
result= String.format("%s",d);
if(result.length()<2)
{
String result2=result;
result="0"+result2;
}
return result;
}
private Runnable animator = new Runnable() {
#Override
public void run() {
boolean needNewFrame = false;
long now = AnimationUtils.currentAnimationTimeMillis();
for (Dynamics dynamics : datapoints) {
dynamics.update(now);
if (!dynamics.isAtRest()) {
needNewFrame = true;
}
}
if (needNewFrame) {
postDelayed(this, 15);
}
invalidate();
}
};
}
I just want to understand where i need to declare scale values, where i need to calc real dimensions in px.. and et.c. to have no memory leaks..
If i remove color change and incrice number of Rects up to 1000 - i get lags.
All methods o any information how to debug memory leaks - you are wellcome!
You have to remove runnable for animation when view is detached.
if (needNewFrame) {
postDelayed(this, 15); <--- memory leak
}
Try like this.
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallback(your runnable);
}
Also refreshing every 15 milliseconds is very heavy.
I am making my own game. I have already made a splash screen and a main menu. I have made a button "Play" in my menu but I can't link it to my main game, while I can link it to other classes.
Here is the code of the class I can't open:
package com.mygdx.Papermadness.screens;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureWrap;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Vector2;
public class PaperMadness extends InputAdapter implements ApplicationListener, Screen {
float timer;
public static Preferences prefs;
public static int counter; // The variable you want to save
private BitmapFont font;
//public int counter = 0;
boolean touch = false;
SpriteBatch batch;
SpriteBatch spriteBatch;
Texture spriteTexture;
Sprite sprite;
float scrollTimer = 0.0f;
Player player;
Paper paper;
Huiz huiz;
Lijn lijn;
String money = String.valueOf(counter);
ShapeRenderer sr;
public boolean kukar = false;
public void create() {
font = new BitmapFont();
Gdx.input.setInputProcessor(this);
player = new Player(new Vector2(50, 100), new Vector2(100, 100));
huiz = new Huiz(new Vector2(200, 300), new Vector2(110, 110));
// huiz = new Huiz(new Vector2(200, 300), new Vector2(110, 110));
paper = new Paper(new Vector2(Gdx.input.getX(),
Gdx.graphics.getHeight() - Gdx.input.getY()), new Vector2(50,
50));
lijn = new Lijn(new Vector2(0, 200), new Vector2(600, 2));
// sr = new ShapeRenderer();
spriteBatch = new SpriteBatch();
spriteTexture = new Texture("b9.png");
spriteTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
sprite = new Sprite(spriteTexture);
sprite.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch = new SpriteBatch();
}
#Override
public void render(float delta) {
// bounds.set(Gdx.input.getX(),
// Gdx.graphics.getHeight() - Gdx.input.getY(),
// secondTexture.getWidth(), secondTexture.getHeight());
scrollTimer += Gdx.graphics.getDeltaTime();
if (scrollTimer > 1.0f)
scrollTimer = 0.0f;
sprite.setV(scrollTimer + 2);
sprite.setV2(scrollTimer);
player.update();
paper.update();
lijn.update();
huiz.update();
/*
* if (tree.getBounds().overlaps(ball.getBounds())) {
* System.out.println("Swendley Programinateur"); }
*
* if (tree.getBounds().overlaps(paper.getBounds())) {
* System.out.println("Souk Programinateur"); }
*/
spriteBatch.begin();
sprite.draw(spriteBatch);
spriteBatch.end();
batch.begin();
player.draw(batch);
huiz.draw(batch);
// paper.draw(batch);
if (Gdx.graphics.getHeight() / 1.25 < Gdx.input.getY()
&& Gdx.graphics.getWidth() / 2.7 < Gdx.input.getX()
&& Gdx.graphics.getWidth() / 1.7 > Gdx.input.getX()
&& Gdx.input.isTouched() && kukar == false && touch == false) {
kukar = true;
touch = true;
} else if (Gdx.input.isTouched() && kukar == true && touch == true) {
paper.draw(batch);
if (paper.getBounds().overlaps(huiz.getBounds())
|| paper.getBounds().overlaps(huiz.getBounds1())) {
// System.out.println("Huis Geraakt!");
touch = false;
counter++;
checkSpeed();
money = Integer.toString(counter);
// System.out.println(counter);
}
}
if (huiz.getBounds().overlaps(lijn.getBounds())
|| huiz.getBounds1().overlaps(lijn.getBounds())){
//System.out.println("Game Over");
}
font.draw(batch, money, Gdx.graphics.getWidth() / 2.06f,
Gdx.graphics.getHeight() / 1.05f);
font.setColor(Color.BLACK);
font.setScale(2, 2);
// house.draw(batch);
// house1.draw(batch);
lijn.draw(batch);
batch.end();
// sr.begin(ShapeType.Filled);
// sr.setColor(Color.YELLOW);
// sr.rect(Gdx.input.getX(), Gdx.graphics.getHeight() -
// Gdx.input.getY(),
// paper.getSize().x, paper.getSize().y);
// sr.setColor(Color.BLACK);
// sr.rect(huiz.getPosition().x, huiz.getPosition().y,
// huiz.getSize().x, huiz.getSize().y);
// sr.rect(house1.getPosition().x, house1.getPosition().y,
// house1.getSize().x, house1.getSize().y);
// sr.end();
}
public static void savePrefs(){
prefs = Gdx.app.getPreferences("game-prefs"); // The name of your prefs files
prefs.putInteger("counter", counter);
prefs.flush();
System.out.println(prefs);
}
public static void loadPrefs(){
prefs = Gdx.app.getPreferences("game-prefs");
counter = prefs.getInteger("counter",0); //Load counter, default to zero if not found
}
public void checkSpeed() {
if (counter <= 7) {
huiz.huisVelocity = 500f;
}
if (counter > 7 && counter <= 17) {
huiz.huisVelocity = 550f;
}
if (counter > 17 && counter <= 30) {
huiz.huisVelocity = 650f;
}
if (counter > 30 && counter <= 50) {
huiz.huisVelocity = 750;
}
if (counter > 50 && counter <= 75) {
huiz.huisVelocity = 900;
}
if (counter > 75 && counter <= 100) {
huiz.huisVelocity = 1000;
}
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
kukar = false;
touch = false;
return true;
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
#Override
public void render() {
}
}
Here is the menu class:
package com.mygdx.Papermadness.screens;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.mygdx.Papermadness.Papermadness;
public class MainMenu implements Screen {
private Stage stage;// done
private TextureAtlas atlas;// done
private Skin skin;// done
private Table table;// done
private TextButton buttonPlay, buttonExit;
private BitmapFont white, black;// done
private Label heading;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Table.drawDebug(stage);
stage.act(delta);
stage.draw();
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
stage = new Stage();
Gdx.input.setInputProcessor(stage);
atlas = new TextureAtlas("ui/button.pack");
skin = new Skin(atlas);
table = new Table(skin);
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
white = new BitmapFont(Gdx.files.internal("font/white.fnt"), false);
black = new BitmapFont(Gdx.files.internal("font/black.fnt"), false);
// maakt buttons
TextButtonStyle textButtonStyle = new TextButtonStyle();
textButtonStyle.up = skin.getDrawable("button.up");
textButtonStyle.down = skin.getDrawable("button.down");
textButtonStyle.pressedOffsetX = 1;
textButtonStyle.pressedOffsetY = -1;
textButtonStyle.font = black;
buttonExit = new TextButton("EXIT", textButtonStyle);
buttonExit.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.exit();
}
});
buttonExit.pad(15);
buttonPlay = new TextButton("PlAY", textButtonStyle);
buttonPlay.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
((Game) Gdx.app.getApplicationListener())
.setScreen(new PaperMadness());
}
});
buttonPlay.pad(15);
// maakt header
heading = new Label(Papermadness.TITLE, new LabelStyle(white,
Color.WHITE));
heading.setFontScale(2);
table.add(heading);
table.getCell(heading).spaceBottom(100);
table.row();
table.add(buttonPlay);
table.getCell(buttonPlay).spaceBottom(15);
table.row();
table.add(buttonExit);
// table.debug();
stage.addActor(table);
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
stage.dispose();
atlas.dispose();
skin.dispose();
white.dispose();
black.dispose();
}
}
public class MyGdxGame extends Game{
public static MenuScreen menuScreen;
public static GameScreen gameScreen;
#Override
public void create(){
menuScreen = new MenuScreen(this);
gameScreen = new GameScreen (this);
setScreen(menuScreen);
}
}
Here is MenuScreen
public class MenuScreen implements Screen{
MyGdxGame game;
public MenuScreen(MyGdxGame game){
this.game = game;
}
////////////when you want to change screen type game.setScreen(game.gameScreen)
...........
...........
}
and this is GameScreen
public class GameScreen implements Screen{
...........
...........
...........
}
this is a simple example , try to do the same in your code.
Here is a good tutorial
https://github.com/libgdx/libgdx/wiki/Extending-the-simple-game
If it helped , let me know about it.
I know its possible to paint the background of canvas using
mPaint = new Paint();
mPaint.setColor(Color.RED);
Im just wondering how to i set a permanent background for it. Ive tried using the xml file but nothing happens. Any ideas?
This is the source code of the project, ive been following a tutorial how to do it because im fairly unfamiliar with bitmaps.
Canvas Class
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.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
public class GameBoard extends View{
private int mFlagX = -1;
private int mFlagY = -1;
private Bitmap mBitmap = null;
private Bitmap nBitmap = null;
private Paint mPaint = null;
private boolean isFlagHidden = false;
private int mBoundX = -1;
private int mBoundY = -1;
//play with these values to make the app more or less challenging
public final int CLOSER = 50;
public final int CLOSE = 100;
public GameBoard(Context context, AttributeSet aSet) {
super(context, aSet);
//load our bitmap
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.star);
//create a paint brush
mPaint = new Paint();
mPaint.setColor(Color.RED);
}
#Override
public void onDraw(Canvas canvas) {
//initialize
if ((mFlagX < 1) || (mFlagY < 1)) {
mFlagX = (int) (getWidth() / 2) - mBitmap.getWidth() / 2;
mFlagY = (int) (getHeight() / 2) - mBitmap.getHeight() / 2;
mBoundX = (int)getWidth() - mBitmap.getWidth();
mBoundY = (int)getHeight() - mBitmap.getHeight();
}
//draw background
canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
//draw the flag
if (!isFlagHidden) {
canvas.drawBitmap(mBitmap, mFlagX, mFlagY, null);
}
}
public void hideTheFlag(){
//randomize flag location
mFlagX = (int) Math.ceil(Math.random() * mBoundX);
mFlagY = (int) Math.ceil(Math.random() * mBoundY);
isFlagHidden = true;
//force redraw
invalidate();
}
public void giveUp(){
isFlagHidden = false;
//force redraw
invalidate();
}
public Indicators takeAGuess(float x, float y) {
//this is our "warm" area
Rect prettyClose = new Rect(mFlagX - CLOSE, mFlagY - CLOSE, mFlagX+mBitmap.getWidth() + CLOSE, mFlagY+mBitmap.getHeight() + CLOSE);
//normalize
if (prettyClose.left < 0) prettyClose.left = 0;
if (prettyClose.top < 0) prettyClose.top = 0;
if (prettyClose.right > mBoundX) prettyClose.right = mBoundX;
if (prettyClose.bottom > mBoundY) prettyClose.bottom = mBoundY;
//this is our "hot" area
Rect reallyClose = new Rect(mFlagX - CLOSER, mFlagY - CLOSER, mFlagX+mBitmap.getWidth() + CLOSER, mFlagY+mBitmap.getHeight() + CLOSER);
//normalize
if (reallyClose.left < 0) reallyClose.left = 0;
if (reallyClose.top < 0) reallyClose.top = 0;
if (reallyClose.right > mBoundX) reallyClose.right = mBoundX;
if (reallyClose.bottom > mBoundY) reallyClose.bottom = mBoundY;
//this is the area that contains our flag
Rect bullsEye = new Rect(mFlagX, mFlagY, mFlagX+mBitmap.getWidth(), mFlagY+mBitmap.getHeight());
//check to see where on the board the user pressed
if (bullsEye.contains((int) x, (int)y)) {
//found it
isFlagHidden = false;
invalidate();
return Indicators.BULLSEYE;
} else if (reallyClose.contains((int) x, (int)y)) {
//hot
return Indicators.HOT;
} else if (prettyClose.contains((int)x, (int)y)) {
//warm
return Indicators.WARM;
} else {
//not even close
return Indicators.COLD;
}
}
}
Game Class
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.TextView;
public class FindTheStar extends Activity implements OnTouchListener, OnClickListener{
private GameBoard mGameBoard = null;
private boolean isFlagHidden = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_star);
mGameBoard = (GameBoard) findViewById(R.id.Hide_canvas);
mGameBoard.setOnTouchListener(this);
Button b = (Button) findViewById(R.id.the_button);
b.setOnClickListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getId() == R.id.Hide_canvas) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (isFlagHidden) {
TextView tv = (TextView)findViewById (R.id.the_label);
switch (mGameBoard.takeAGuess(event.getX(), event.getY())) {
case BULLSEYE:
Button b = (Button) findViewById(R.id.the_button);
isFlagHidden = false;
b.setText("Go Hide!");
tv.setText("You found me!");
tv.setTextColor(Color.GREEN);
break;
case HOT:
tv.setText("You're hot!");
tv.setTextColor(Color.RED);
break;
case WARM:
tv.setText("Getting warm...");
tv.setTextColor(Color.YELLOW);
break;
case COLD:
tv.setText("You're cold.");
tv.setTextColor(Color.BLUE);
break;
}
}
}
return true;
}
return false;
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.the_button) {
TextView tv = (TextView)findViewById (R.id.the_label);
tv.setText("");
Button b = (Button) findViewById(R.id.the_button);
isFlagHidden = !isFlagHidden;
if (isFlagHidden) {
b.setText("Can't find me?");
mGameBoard.hideTheFlag();
} else {
b.setText("Go Hide!");
mGameBoard.giveUp();
}
}
}
}
XML File
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/the_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textSize="20sp"
android:layout_marginBottom="10dip"
android:text="Lets Play Hide and Seek!"/>
<Button
android:id="#+id/the_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:layout_marginBottom="10dip"
android:text="Go Hide!"/>
<app.autismapp.GameBoard
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/Hide_canvas"/>
</LinearLayout>
yes you can set your permanent background using xml layout..i done this by creating two class.
this is my code in MainACtivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final BrushView view=new BrushView(this);
setContentView(R.layout.mylayout);//removed this one if the paint doesnt work
view.setBackgroundResource(R.drawable.background);//to set background
setContentView(view);// to display the background
and my second class
public class PaintView extends View {
private Paint paint = new Paint();
public LayoutParams params;
public PaintView(Context context) {
super(context);
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
i hope it gives you an idea
Suppose I have multiple Images that I need to put one on top of the other, some might have some kind of animation appearing and some might even be draggable.
the largest one which usually takes the whole screen would be the bottom in the Z-coordinate (let's call it the backgroundImageView ), while all of the rest appear on top of it (and on top of others).
like so:
backgroundImageView
imageView1 , centered.
imageView2 , at 60%,60% of the top left corner
...
If I use a FrameLayout (which seems like the best solution), the backgroundImageView would have its size fit nicely, but how can I force the other layers resize themselves accordingly?
I think I need to somehow get where to put the other layers and how to set their sizes.
The easy way is to make sure all layers have the exact same size, but that could take a lot of memory and become very slow when animating or dragging views. It would be a huge waste if some of the layers have a very small content.
this is a class that displays an image with additional layers:
import java.util.ArrayList;
import java.util.Iterator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
import android.widget.ImageView;
public class LayeredImageView extends ImageView {
private final static String TAG = "LayeredImageView";
private ArrayList<Layer> mLayers;
private Matrix mDrawMatrix;
private Resources mResources;
public LayeredImageView(Context context) {
super(context);
init();
}
public LayeredImageView(Context context, AttributeSet set) {
super(context, set);
init();
int[] attrs = {
android.R.attr.src
};
TypedArray a = context.obtainStyledAttributes(set, attrs);
TypedValue outValue = new TypedValue();
if (a.getValue(0, outValue)) {
setImageResource(outValue.resourceId);
}
a.recycle();
}
private void init() {
mLayers = new ArrayList<Layer>();
mDrawMatrix = new Matrix();
mResources = new LayeredImageViewResources();
}
#Override
protected boolean verifyDrawable(Drawable dr) {
for (int i = 0; i < mLayers.size(); i++) {
Layer layer = mLayers.get(i);
if (layer.drawable == dr) {
return true;
}
}
return super.verifyDrawable(dr);
}
#Override
public void invalidateDrawable(Drawable dr) {
if (verifyDrawable(dr)) {
invalidate();
} else {
super.invalidateDrawable(dr);
}
}
#Override
public Resources getResources() {
return mResources;
}
#Override
public void setImageBitmap(Bitmap bm) throws RuntimeException {
String detailMessage = "setImageBitmap not supported, use: setImageDrawable() " +
"or setImageResource()";
throw new RuntimeException(detailMessage);
}
#Override
public void setImageURI(Uri uri) throws RuntimeException {
String detailMessage = "setImageURI not supported, use: setImageDrawable() " +
"or setImageResource()";
throw new RuntimeException(detailMessage);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Matrix matrix = getImageMatrix();
if (matrix != null) {
int numLayers = mLayers.size();
boolean pendingAnimations = false;
for (int i = 0; i < numLayers; i++) {
mDrawMatrix.set(matrix);
Layer layer = mLayers.get(i);
if (layer.matrix != null) {
mDrawMatrix.preConcat(layer.matrix);
}
if (layer.animation == null) {
draw(canvas, layer.drawable, mDrawMatrix, 255);
} else {
Animation a = layer.animation;
if (!a.isInitialized()) {
Rect bounds = layer.drawable.getBounds();
Drawable parentDrawable = getDrawable();
if (parentDrawable != null) {
Rect parentBounds = parentDrawable.getBounds();
a.initialize(bounds.width(), bounds.height(), parentBounds.width(), parentBounds.height());
} else {
a.initialize(bounds.width(), bounds.height(), 0, 0);
}
}
long currentTime = AnimationUtils.currentAnimationTimeMillis();
boolean running = a.getTransformation(currentTime, layer.transformation);
if (running) {
// animation is running: draw animation frame
Matrix animationFrameMatrix = layer.transformation.getMatrix();
mDrawMatrix.preConcat(animationFrameMatrix);
int alpha = (int) (255 * layer.transformation.getAlpha());
// Log.d(TAG, "onDraw ********** [" + i + "], alpha: " + alpha + ", matrix: " + animationFrameMatrix);
draw(canvas, layer.drawable, mDrawMatrix, alpha);
pendingAnimations = true;
} else {
// animation ended: set it to null
layer.animation = null;
draw(canvas, layer.drawable, mDrawMatrix, 255);
}
}
}
if (pendingAnimations) {
// invalidate if any pending animations
invalidate();
}
}
}
private void draw(Canvas canvas, Drawable drawable, Matrix matrix, int alpha) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.concat(matrix);
drawable.setAlpha(alpha);
drawable.draw(canvas);
canvas.restore();
}
public Layer addLayer(Drawable d, Matrix m) {
Layer layer = new Layer(d, m);
mLayers.add(layer);
invalidate();
return layer;
}
public Layer addLayer(Drawable d) {
return addLayer(d, null);
}
public Layer addLayer(int idx, Drawable d, Matrix m) {
Layer layer = new Layer(d, m);
mLayers.add(idx, layer);
invalidate();
return layer;
}
public Layer addLayer(int idx, Drawable d) {
return addLayer(idx, d, null);
}
public void removeLayer(Layer layer) {
layer.valid = false;
mLayers.remove(layer);
}
public void removeAllLayers() {
Iterator<Layer> iter = mLayers.iterator();
while (iter.hasNext()) {
LayeredImageView.Layer layer = iter.next();
layer.valid = false;
iter.remove();
}
invalidate();
}
public int getLayersSize() {
return mLayers.size();
}
public class Layer {
private Drawable drawable;
private Animation animation;
private Transformation transformation;
private Matrix matrix;
private boolean valid;
private Layer(Drawable d, Matrix m) {
drawable = d;
transformation = new Transformation();
matrix = m;
valid = true;
Rect bounds = d.getBounds();
if (bounds.isEmpty()) {
if (d instanceof BitmapDrawable) {
int right = d.getIntrinsicWidth();
int bottom = d.getIntrinsicHeight();
d.setBounds(0, 0, right, bottom);
} else {
String detailMessage = "drawable bounds are empty, use d.setBounds()";
throw new RuntimeException(detailMessage);
}
}
d.setCallback(LayeredImageView.this);
}
public void startLayerAnimation(Animation a) throws RuntimeException {
if (!valid) {
String detailMessage = "this layer has already been removed";
throw new RuntimeException(detailMessage);
}
transformation.clear();
animation = a;
if (a != null) {
a.start();
}
invalidate();
}
public void stopLayerAnimation(int idx) throws RuntimeException {
if (!valid) {
String detailMessage = "this layer has already been removed";
throw new RuntimeException(detailMessage);
}
if (animation != null) {
animation = null;
invalidate();
}
}
}
private class LayeredImageViewResources extends Resources {
public LayeredImageViewResources() {
super(getContext().getAssets(), new DisplayMetrics(), null);
}
#Override
public Drawable getDrawable(int id) throws NotFoundException {
Drawable d = super.getDrawable(id);
if (d instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) d;
bd.getBitmap().setDensity(DisplayMetrics.DENSITY_DEFAULT);
bd.setTargetDensity(DisplayMetrics.DENSITY_DEFAULT);
}
return d;
}
}
}
and how it can be used:
final LayeredImageView v = new LayeredImageView(this);
Resources res = v.getResources();
v.setImageResource(R.drawable.background);
Matrix m;
m = new Matrix();
m.preTranslate(81, 146); // pixels to offset
final Layer layer1 = v.addLayer(res.getDrawable(R.drawable.layer1), m);
m = new Matrix();
m.preTranslate(62, 63); // pixels to offset
final Layer layer0 = v.addLayer(0, res.getDrawable(R.drawable.layer0), m);
final AnimationDrawable ad = new AnimationDrawable();
ad.setOneShot(false);
Drawable frame1, frame2;
frame1 = res.getDrawable(R.drawable.layer0);
frame2 = res.getDrawable(R.drawable.layer1);
ad.addFrame(frame1, 3000);
ad.addFrame(frame2, 1000);
ad.addFrame(frame1, 250);
ad.addFrame(frame2, 250);
ad.addFrame(frame1, 250);
ad.addFrame(frame2, 250);
ad.addFrame(frame1, 250);
ad.addFrame(frame2, 250);
ad.setBounds(200, 20, 300, 120);
v.addLayer(1, ad);
v.post(new Runnable() {
#Override
public void run() {
ad.start();
}
});
int[] colors = {
0xeeffffff,
0xee0038a8,
0xeece1126,
};
GradientDrawable gd = new GradientDrawable(Orientation.TOP_BOTTOM, colors);
gd.setBounds(0, 0, 100, 129);
gd.setCornerRadius(20);
gd.setStroke(5, 0xaa666666);
final Matrix mm = new Matrix();
mm.preTranslate(200, 69); // pixels to offset
mm.preRotate(20, 50, 64.5f);
final Layer layer2 = v.addLayer(2, gd, mm);
final Animation as = AnimationUtils.loadAnimation(this, R.anim.anim_set);
final Runnable action1 = new Runnable() {
#Override
public void run() {
Animation a;
Interpolator i;
i = new Interpolator() {
#Override
public float getInterpolation(float input) {
return (float) Math.sin(input * Math.PI);
}
};
as.setInterpolator(i);
layer0.startLayerAnimation(as);
a = new TranslateAnimation(0, 0, 0, 100);
a.setDuration(3000);
i = new Interpolator() {
#Override
public float getInterpolation(float input) {
float output = (float) Math.sin(Math.pow(input, 2.5f) * 12 * Math.PI);
return (1-input) * output;
}
};
a.setInterpolator(i);
layer1.startLayerAnimation(a);
a = new AlphaAnimation(0, 1);
i = new Interpolator() {
#Override
public float getInterpolation(float input) {
return (float) (1 - Math.sin(input * Math.PI));
}
};
a.setInterpolator(i);
a.setDuration(2000);
layer2.startLayerAnimation(a);
}
};
OnClickListener l1 = new OnClickListener() {
#Override
public void onClick(View view) {
action1.run();
}
};
v.setOnClickListener(l1);
v.postDelayed(action1, 2000);
// final float[] values = new float[9];
// final float[] pts = new float[2];
// final Matrix inverse = new Matrix();;
// OnTouchListener l = new OnTouchListener() {
// #Override
// public boolean onTouch(View view, MotionEvent event) {
// int action = event.getAction();
// if (action != MotionEvent.ACTION_UP) {
// if (inverse.isIdentity()) {
// v.getImageMatrix().invert(inverse);
// Log.d(TAG, "onTouch set inverse");
// }
// pts[0] = event.getX();
// pts[1] = event.getY();
// inverse.mapPoints(pts);
//
// mm.getValues(values);
// // gd's bounds are (0, 0, 100, 129);
// values[Matrix.MTRANS_X] = pts[0] - 100 / 2;
// values[Matrix.MTRANS_Y] = pts[1] - 129 / 2;
// mm.setValues(values);
// v.invalidate();
// }
// return false;
// }
// };
// v.setOnTouchListener(l);
setContentView(v);
anim_set.xml looks like:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="true"
>
<rotate
android:fromDegrees="0"
android:toDegrees="30"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2500"
/>
<scale
android:fromXScale="1"
android:toXScale="1.8"
android:fromYScale="1"
android:toYScale="1.8"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2500"
/>
</set>
with the following images:
background.png:
layer0.png:
layer1.png:
the result is:
IMPORTANT in order to prevent resources from auto OS scaling when loading from different drawable-* folders you have to use Resources object obtained from LayeredImageView.getResources() method
have fun!
just extend ImageView and override its onDraw method in order to draw additional layers
this is a minimal varsion (enhanced version with animations is in the second answer):
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
public class LayeredImageView extends ImageView {
private final static String TAG = "LayeredImageView";
ArrayList<Bitmap> mLayers;
public LayeredImageView(Context context) {
super(context);
init();
}
public LayeredImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mLayers = new ArrayList<Bitmap>();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Matrix matrix = getImageMatrix();
if (matrix != null) {
int numLayers = mLayers.size();
for (int i = 0; i < numLayers; i++) {
Bitmap b = mLayers.get(i);
canvas.drawBitmap(b, matrix, null);
}
}
}
public void addLayer(Bitmap b) {
mLayers.add(b);
invalidate();
}
public void addLayer(int idx, Bitmap b) {
mLayers.add(idx, b);
invalidate();
}
public void removeLayer(int idx) {
mLayers.remove(idx);
}
public void removeAllLayers() {
mLayers.clear();
invalidate();
}
public int getLayersSize() {
return mLayers.size();
}
}
and how its used in your Activity:
LayeredImageView v = new LayeredImageView(this);
v.setImageResource(R.drawable.background);
Resources res = getResources();
v.addLayer(BitmapFactory.decodeResource(res, R.drawable.layer0));
v.addLayer(0, BitmapFactory.decodeResource(res, R.drawable.layer1));
setContentView(v);
here you have 3 images:
background.png
layer0.png
layer1.png
and three above combined
and finally the captured screen from the emulator
just tell me how i change text view position in this code? in this app application show result textview at top left position of application how to i change is position to botton center or right side i try layout position in xml but is always show on top left result barcode value on same location where button present and button overlap resultText view value s o how can i change textview position?????
package com.zijunlin.Zxing.Demo;
import java.io.IOException;
import java.util.Vector;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.zijunlin.Zxing.Demo.camera.CameraManager;
import com.zijunlin.Zxing.Demo.decoding.CaptureActivityHandler;
import com.zijunlin.Zxing.Demo.decoding.InactivityTimer;
import com.zijunlin.Zxing.Demo.view.ViewfinderView;
import android.R.string;
import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class CaptureActivity extends Activity implements Callback {
private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
private boolean hasSurface;
private Vector<BarcodeFormat> decodeFormats;
private String characterSet;
public static TextView txtResult;
private InactivityTimer inactivityTimer;
private MediaPlayer mediaPlayer;
private boolean playBeep;
private static final float BEEP_VOLUME = 0.10f;
private boolean vibrate;
private static String barCode;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//³õʼ»¯ CameraManager
CameraManager.init(getApplication());
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
txtResult = (TextView) findViewById(R.id.txtResult);
Button mybutton = (Button) findViewById(R.id.button1);
mybutton.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
Toast.makeText(CaptureActivity.this,""+barCode,
Toast.LENGTH_LONG).show();
}
});
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
}
#Override
protected void onResume() {
super.onResume();
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
} else {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
decodeFormats = null;
characterSet = null;
playBeep = true;
AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep = false;
}
initBeepSound();
vibrate = true;
}
#Override
protected void onPause() {
super.onPause();
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
CameraManager.get().closeDriver();
}
#Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
}
private void initCamera(SurfaceHolder surfaceHolder) {
try {
CameraManager.get().openDriver(surfaceHolder);
} catch (IOException ioe) {
return;
} catch (RuntimeException e) {
return;
}
if (handler == null) {
handler = new CaptureActivityHandler(this, decodeFormats,
characterSet);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
public ViewfinderView getViewfinderView() {
return viewfinderView;
}
public Handler getHandler() {
return handler;
}
public void drawViewfinder() {
viewfinderView.drawViewfinder();
}
public void handleDecode(Result obj, Bitmap barcode) {
inactivityTimer.onActivity();
viewfinderView.drawResultBitmap(barcode);
playBeepSoundAndVibrate();
txtResult.setText(obj.getBarcodeFormat().toString() + ":"
+ obj.getText());
barCode=obj.getText().toString();
//TextView t = (TextView)findViewById(R.id.txtResult2);
//t.setText("SEcond code here"+barCode);
}
private void initBeepSound() {
if (playBeep && mediaPlayer == null) {
// The volume on STREAM_SYSTEM is not adjustable, and users
found it
// too loud,
// so we now play on the music stream.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(beepListener);
AssetFileDescriptor file = getResources().openRawResourceFd(
R.raw.beep);
try {
mediaPlayer.setDataSource(file.getFileDescriptor(),
file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
mediaPlayer.prepare();
} catch (IOException e) {
mediaPlayer = null;
}
}
}
private static final long VIBRATE_DURATION = 200L;
private void playBeepSoundAndVibrate() {
if (playBeep && mediaPlayer != null) {
mediaPlayer.start();
}
if (vibrate) {
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_DURATION);
}
}
/**
* When the beep has finished playing, rewind to queue up another one.
*/
private final OnCompletionListener beepListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
};
}
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<SurfaceView android:id="#+id/preview_view"
android:layout_width="fill_parent"
android:layout_gravity="center"
android:layout_height="fill_parent"
android:layout_centerInParent="true"/>
<com.zijunlin.Zxing.Demo.view.ViewfinderView
android:id="#+id/viewfinder_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/transparent"/>
<TextView android:id="#+id/txtResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dip"
android:text="hello"
android:textSize="14sp"/>
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dip"
android:layout_marginRight="30dip"
android:text="Button" />
</FrameLayout>
package com.zijunlin.Zxing.Demo.view;
import com.google.zxing.ResultPoint;
import com.zijunlin.Zxing.Demo.R;
import com.zijunlin.Zxing.Demo.camera.CameraManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import java.util.Collection;
import java.util.HashSet;
/**
* This view is overlaid on top of the camera preview. It adds the viewfinder
rectangle and partial
* transparency outside it, as well as the laser scanner animation and result points.
*
* #author dswitkin#google.com (Daniel Switkin)
*/
public final class ViewfinderView extends View {
private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
private static final long ANIMATION_DELAY = 100L;
private static final int OPAQUE = 0xFF;
private final Paint paint;
private Bitmap resultBitmap;
private final int maskColor;
private final int resultColor;
private final int frameColor;
private final int laserColor;
private final int resultPointColor;
private int scannerAlpha;
private Collection<ResultPoint> possibleResultPoints;
private Collection<ResultPoint> lastPossibleResultPoints;
// This constructor is used when the class is built from an XML resource.
public ViewfinderView(Context context, AttributeSet attrs) {
super(context, attrs);
// Initialize these once for performance rather than calling them every time in
onDraw().
paint = new Paint();
Resources resources = getResources();
maskColor = resources.getColor(R.color.viewfinder_mask);
resultColor = resources.getColor(R.color.result_view);
frameColor = resources.getColor(R.color.viewfinder_frame);
laserColor = resources.getColor(R.color.viewfinder_laser);
resultPointColor = resources.getColor(R.color.possible_result_points);
scannerAlpha = 0;
possibleResultPoints = new HashSet<ResultPoint>(5);
}
#Override
public void onDraw(Canvas canvas) {
Rect frame = CameraManager.get().getFramingRect();
if (frame == null) {
return;
}
int width = canvas.getWidth();
int height = canvas.getHeight();
// Draw the exterior (i.e. outside the framing rect) darkened
paint.setColor(resultBitmap != null ? resultColor : maskColor);
canvas.drawRect(0, 0, width, frame.top, paint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
canvas.drawRect(0, frame.bottom + 1, width, height, paint);
if (resultBitmap != null) {
// Draw the opaque result bitmap over the scanning rectangle
paint.setAlpha(OPAQUE);
canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
} else {
// Draw a two pixel solid black border inside the framing rect
paint.setColor(frameColor);
canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1,
paint);
canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1,
paint);
// Draw a red "laser scanner" line through the middle to show decoding is active
paint.setColor(laserColor);
paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
int middle = frame.height() / 2 + frame.top;
canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
Collection<ResultPoint> currentPossible = possibleResultPoints;
Collection<ResultPoint> currentLast = lastPossibleResultPoints;
if (currentPossible.isEmpty()) {
lastPossibleResultPoints = null;
} else {
possibleResultPoints = new HashSet<ResultPoint>(5);
lastPossibleResultPoints = currentPossible;
paint.setAlpha(OPAQUE);
paint.setColor(resultPointColor);
for (ResultPoint point : currentPossible) {
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f,
paint);
}
}
if (currentLast != null) {
paint.setAlpha(OPAQUE / 2);
paint.setColor(resultPointColor);
for (ResultPoint point : currentLast) {
canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f,
paint);
}
}
// Request another update at the animation interval, but only repaint the laser line,
// not the entire viewfinder mask.
postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right,
frame.bottom);
}
}
public void drawViewfinder() {
resultBitmap = null;
invalidate();
}
/**
* Draw a bitmap with the result points highlighted instead of the live scanning
display.
*
* #param barcode An image of the decoded barcode.
*/
public void drawResultBitmap(Bitmap barcode) {
resultBitmap = barcode;
invalidate();
}
public void addPossibleResultPoint(ResultPoint point) {
possibleResultPoints.add(point);
}
}
Use the attribute android:gravity in XML like this :
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:gravity="right"
android:text="TextView" />
Or if you want to change programmatically, use this :
myTextView.setGravity(Gravity.RIGHT);
if your textView has fill_parent in layout params #Deepanker Chaudhary's solution is right.
but your textView has wrap_content like sizes in layoutparams you should use margins.