In Android, when is an Interface called? - java

This is my first attempt at an Android game. I need to draw a path that starts at the center of the screen, and I'm getting the center screen coordinates using OnGlobalLayoutListener. In order to pass the center coordinates to my View class I'm using an Interface. Now, assuming that the Interface is working, it's passing 0,0 because the drawn path is starting at the upper left of my Relative Layout. I'm getting the correct coordinates because for now I'm passing them to a TextView so I can see the coordinates, but they're not getting passed to the View class because the path starts in the upper left, not the center of my Relative Layout. So I guess my question is: Does the Interface get triggered before onCreate completes? And if so, how can I get the center screen data to the Interface before the Interface is triggered? Can I somehow trigger the Interface after I get the screen data? Here are the classes I'm working with, first the Main Activity:
public class Game1 extends Activity implements GBoardValueSetter {
DrawPath dp;
TextView gameScore_TV, gameTime_TV;
private CountDownTimer mainGameCD;
private boolean mainGameTimerHasStarted = false;
private final long mainCDTime = 30 * 1000;
private final long mainCDInterval = 1 * 1000;
// ---GameBoard variables
RelativeLayout root_RL, gBoardInfo_RL, gBoard_RL;
LayoutInflater LayInf = null;
View root_VUE, gBoardInfo_VUE;
LayoutParams root_LP, gBoardInfo_LP, gBoard_LP;
int xScr2Int, yScr2Int, xScrInt, yScrInt, xCenterInt, yCenterInt;
String xCenterStr, yCenterStr, xHStr, yWStr;
float xCenter_FL, yCenter_FL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.cutin, R.anim.cutout);
root_RL = new RelativeLayout(this);
root_LP = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
root_RL.setId(1);
root_RL.setBackgroundColor(Color.WHITE);
root_RL.setLayoutParams(root_LP);
setContentView(root_RL);
createBlankGBoard();
addDP();
}// --- END onCreate
//--- Interface call
#Override
public void passGBCenterIntValuesInterface(int xC_IInt, int yC_IInt) {
xC_IInt = xCenterInt;
yC_IInt = yCenterInt;
dp.setCenterInt(xC_IInt, yC_IInt);
}//--- END Interface call
public void createBlankGBoard(){
LayInf = (LayoutInflater) getApplicationContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
gBoardInfo_VUE = LayInf.inflate(R.layout.game1_info, null);
gBoardInfo_LP = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
gBoardInfo_LP.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
gBoardInfo_VUE.setId(2);
gBoardInfo_VUE.setLayoutParams(gBoardInfo_LP);
gameTime_TV = (TextView) gBoardInfo_VUE.findViewById(R.id.game1_timeValue2_TV);
gameScore_TV = (TextView) gBoardInfo_VUE.findViewById(R.id.game1_scoreValue2_TV);
root_RL.addView(gBoardInfo_VUE);
gBoard_RL = new RelativeLayout(this);
gBoard_LP = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
gBoard_LP.addRule(RelativeLayout.BELOW, gBoardInfo_VUE.getId());
gBoard_LP.setMargins(10, 10, 10, 10);
gBoard_RL.setLayoutParams(gBoard_LP);
gBoard_RL.setBackgroundColor(Color.MAGENTA);
root_RL.addView(gBoard_RL);
getGameBoardNumbers();
}
public void addDP(){
root_RL.removeView(gBoard_RL);
dp = new DrawPath(this);
gBoard_RL.setBackgroundColor(Color.CYAN);
gBoard_RL.addView(dp);
root_RL.addView(gBoard_RL);
}
//-- Get GameBoard info using oGLL
public void getGameBoardNumbers(){
gBoard_RL.getViewTreeObserver().addOnGlobalLayoutListener(
NumbersoGLL);
}
//-- oGLL
OnGlobalLayoutListener NumbersoGLL = new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
xScrInt = gBoard_RL.getWidth();
yScrInt = gBoard_RL.getHeight();
xScr2Int = gBoard_RL.getWidth()/2;
yScr2Int = gBoard_RL.getHeight()/2;
xCenterInt = gBoard_RL.getLeft() + xScr2Int;
yCenterInt = gBoard_RL.getTop() + yScr2Int;
xHStr = String.valueOf(xScrInt);
yWStr = String.valueOf(yScrInt);
xCenter_FL = (float)xCenterInt;
yCenter_FL = (float)yCenterInt;
String xCInt_Str = String.valueOf(xCenterInt);
String yCInt_Str = String.valueOf(yCenterInt);
gameScore_TV.setText(xCInt_Str + ", " + yCInt_Str);
}
};
}
Here's the View Class:
public class DrawPath extends View {
Paint paint = new Paint();
Path path = new Path();
private int xC_Int, yC_Int;
class Pt {
float x, y;
Pt(float _x, float _y) {
x = _x;
y = _y;
}
}
public void setCenterInt(int xC_IInt, int yC_IInt){
this.xC_Int = xC_IInt;
this.yC_Int = yC_IInt;
}
Pt[] thePath = { new Pt(xC_Int, yC_Int),
new Pt(200, 200),
new Pt(200, 500),
new Pt(400, 500)
};
public DrawPath(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.RED);
paint.setStrokeWidth(7);
paint.setStyle(Paint.Style.STROKE);
path.moveTo(thePath[0].x, thePath[0].y);
for (int i = 1; i < thePath.length; i++) {
path.lineTo(thePath[i].x, thePath[i].y);
}
canvas.drawPath(path, paint);
}
}
And the Interface Class:
public interface GBoardValueSetter {
void passGBCenterIntValuesInterface(int xC_IInt, int yC_IInt);
}

In your interface call to your activity, you assign the parameters you get from the call:
public void passGBCenterIntValuesInterface(int xC_IInt, int yC_IInt) {
xC_IInt = xCenterInt; <-- RIGHT THERE
yC_IInt = yCenterInt; <-- RIGHT THERE
dp.setCenterInt(xC_IInt, yC_IInt);
}//--- END Interface call
xCenterInt and yCenterInt are problably 0

Related

Hide element when AutoCompleteTextView gain focus

I have 3 AutoCompleteTextView and I want to make a simple function to detect whenever it gain/loses focus so I'll hide an imageView.
Or maybe, whenever the keyboard is UP I want to hide my logo (imageView). When the keyboard is down, show the imageView again.
Code so far:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
RelativeLayout layout = (RelativeLayout)findViewById(R.id.mainLayout);
for(int i=0; i< layout.getChildCount(); i++) {
View v = layout.getChildAt(i);
if(v instanceof AutoCompleteTextView) {
v.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
// if(hasWindowFocus()) {
// ImageView logo = findViewById(R.id.imgLogo);
// logo.setVisibility(View.GONE);
// }
Toast.makeText(getApplicationContext(), "pimba", Toast.LENGTH_LONG).show();
}
});
}
}
}
Also, is it possible to create listeners outside this onCreate() ? Or creating everything inside this function is the right way to go?
Try this
Solution 1
Call this method in onCreate()
private void initKeyBoardListener() {
//Threshold for minimal keyboard height.
final int MIN_KEYBOARD_HEIGHT_PX = 150;
//Top-level window decor view.
final View decorView = getWindow().getDecorView();
// Register global layout listener.
decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
// Retrieve visible rectangle inside window.
private final Rect windowVisibleDisplayFrame = new Rect();
private int lastVisibleDecorViewHeight;
#Override
public void onGlobalLayout() {
decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame);
final int visibleDecorViewHeight = windowVisibleDisplayFrame.height();
if (lastVisibleDecorViewHeight != 0) {
if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) {
Log.d("Keyboard", "SHOW");
// Hide imageview
} else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) {
// Show imageview
Log.d("Keyboard", "HIDE");
}
}
// Save current decor view height for the next call.
lastVisibleDecorViewHeight = visibleDecorViewHeight;
}
});
}
Solution 2
Use this Util class
import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import java.util.HashMap;
/**
* Created by Raman on 2/10/2017.
*/
public class KeyboardUtils implements ViewTreeObserver.OnGlobalLayoutListener {
private static HashMap<SoftKeyboardToggleListener, KeyboardUtils> sListenerMap = new HashMap<>();
private SoftKeyboardToggleListener mCallback;
private View mRootView;
private float mScreenDensity = 1;
private KeyboardUtils(Activity act, SoftKeyboardToggleListener listener) {
mCallback = listener;
mRootView = ((ViewGroup) act.findViewById(android.R.id.content)).getChildAt(0);
mRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
mScreenDensity = act.getResources().getDisplayMetrics().density;
}
public static void addKeyboardToggleListener(Activity act, SoftKeyboardToggleListener listener) {
removeKeyboardToggleListener(listener);
sListenerMap.put(listener, new KeyboardUtils(act, listener));
}
public static void removeKeyboardToggleListener(SoftKeyboardToggleListener listener) {
if (sListenerMap.containsKey(listener)) {
KeyboardUtils k = sListenerMap.get(listener);
k.removeListener();
sListenerMap.remove(listener);
}
}
public static void removeAllKeyboardToggleListeners() {
for (SoftKeyboardToggleListener l : sListenerMap.keySet())
sListenerMap.get(l).removeListener();
sListenerMap.clear();
}
#Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
mRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
float dp = heightDiff / mScreenDensity;
if (mCallback != null)
mCallback.onToggleSoftKeyboard(dp > 200);
}
private void removeListener() {
mCallback = null;
mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
public interface SoftKeyboardToggleListener {
void onToggleSoftKeyboard(boolean isVisible);
}
}
And its usage
Call this in onCreate()
KeyboardUtils.addKeyboardToggleListener(getActivity(), new KeyboardUtils.SoftKeyboardToggleListener() {
#Override
public void onToggleSoftKeyboard(boolean isVisible) {
Log.d("keyboard", "keyboard visible: " + isVisible);
if (!isVisible) {
// show imageview
}
else
{
// hide imageview
}
}
});

How can I create an animation class to use in other activities in android?

I have this animation activity for falling images. It works perfectly. What I would like to is change this, so I can call something like, startImageFallAnimation(), in another activity, and have it show over the current activity. I'd hate to have to add all this code to every activity I want to use it in. I experimented for a few hours, with no luck.
How can I accomplish this?
import com.tmp.animation.R;
public class FallAnimationActivity extends Activity {
// 100 = lots falling / 1000 = less falling
public int imageInterval = 100;
private int[] LEAVES = {
R.drawable.coin,
R.drawable.starsm,
//R.drawable.leaf_yellow,
//R.drawable.leaf_other,
};
private Rect mDisplaySize = new Rect();
private RelativeLayout mRootLayout;
private ArrayList<View> mAllImageViews = new ArrayList<View>();
private float mScale;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Display display = getWindowManager().getDefaultDisplay();
display.getRectSize(mDisplaySize);
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
mScale = metrics.density;
mRootLayout = (RelativeLayout) findViewById(R.id.main_layout);
new Timer().schedule(new ExeTimerTask(), 0, imageInterval);
}
public void create() {
setContentView(R.layout.main);
Display display = getWindowManager().getDefaultDisplay();
display.getRectSize(mDisplaySize);
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
mScale = metrics.density;
mRootLayout = (RelativeLayout) findViewById(R.id.main_layout);
new Timer().schedule(new ExeTimerTask(), 0, imageInterval);
}
public void startAnimation(final ImageView aniView) {
aniView.setPivotX(aniView.getWidth()/2);
aniView.setPivotY(aniView.getHeight()/2);
long delay = new Random().nextInt(Constants.MAX_DELAY);
final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(Constants.ANIM_DURATION);
animator.setInterpolator(new AccelerateInterpolator());
animator.setStartDelay(delay);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
int angle = 50 + (int)(Math.random() * 101);
int movex = new Random().nextInt(mDisplaySize.right);
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = ((Float) (animation.getAnimatedValue())).floatValue();
aniView.setRotation(angle*value);
aniView.setTranslationX((movex-40)*value);
aniView.setTranslationY((mDisplaySize.bottom + (150*mScale))*value);
}
});
animator.start();
}
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int viewId = new Random().nextInt(LEAVES.length);
Drawable d = getResources().getDrawable(LEAVES[viewId]);
LayoutInflater inflate = LayoutInflater.from(FallAnimationActivity.this);
ImageView imageView = (ImageView) inflate.inflate(R.layout.ani_image_view, null);
imageView.setImageDrawable(d);
mRootLayout.addView(imageView);
mAllImageViews.add(imageView);
LayoutParams animationLayout = (LayoutParams) imageView.getLayoutParams();
animationLayout.setMargins(0, (int)(-150*mScale), 0, 0);
animationLayout.width = (int) (60*mScale);
animationLayout.height = (int) (60*mScale);
startAnimation(imageView);
}
};
private class ExeTimerTask extends TimerTask {
#Override
public void run() {
// we don't really use the message 'what' but we have to specify something.
mHandler.sendEmptyMessage(Constants.EMPTY_MESSAGE_WHAT);
}
}
}
EDIT- After lots of work, this is the best I've got, but I cant solve passing context into the handler, or passing the layout into the first method.
import com.tmp.animation.R;
public class FallPop {
private static final String TAG = FallPop.class.toString();
private static final FallPop INSTANCE = new FallPop();
private int[] LEAVES = {
R.drawable.leaf_green,
R.drawable.leaf_red,
R.drawable.leaf_yellow,
R.drawable.leaf_other,
};
private Rect mDisplaySize = new Rect();
private RelativeLayout mRootLayout;
private ArrayList<View> mAllImageViews = new ArrayList<View>();
private float mScale;
private FallPop(){
}
public static FallPop getInstance() {
return INSTANCE;
}
public Context context;
public Context context2;
int count = 0;
public void doAnim(Context context){
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
display.getRectSize(mDisplaySize);
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
mScale = metrics.density;
// FIX!!!
// mRootLayout = (RelativeLayout) findViewById(R.id.main_layout);
new Timer().schedule(new ExeTimerTask(), 0, 200);
}
public void startAnimation(final ImageView aniView) {
aniView.setPivotX(aniView.getWidth()/2);
aniView.setPivotY(aniView.getHeight()/2);
long delay = new Random().nextInt(Constants.MAX_DELAY);
final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(Constants.ANIM_DURATION);
animator.setInterpolator(new AccelerateInterpolator());
animator.setStartDelay(delay);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
int angle = 50 + (int)(Math.random() * 101);
int movex = new Random().nextInt(mDisplaySize.right);
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = ((Float) (animation.getAnimatedValue())).floatValue();
aniView.setRotation(angle*value);
aniView.setTranslationX((movex-40)*value);
aniView.setTranslationY((mDisplaySize.bottom + (150*mScale))*value);
}
});
animator.start();
}
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int viewId = new Random().nextInt(LEAVES.length);
// Need some context here \/
Drawable d = ContextCompat.getDrawable(context, LEAVES[viewId]);
// Original line, also didnt work \/
//Drawable d = getResources().getDrawable(LEAVES[viewId]);
LayoutInflater inflate = LayoutInflater.from(context);
ImageView imageView = (ImageView) inflate.inflate(R.layout.ani_image_view, null);
imageView.setImageDrawable(d);
mRootLayout.addView(imageView);
mAllImageViews.add(imageView);
RelativeLayout.LayoutParams animationLayout = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
animationLayout.setMargins(0, (int) (-150 * mScale), 0, 0);
animationLayout.width = (int) (60 * mScale);
animationLayout.height = (int) (60 * mScale);
startAnimation(imageView);
}
};
class ExeTimerTask extends TimerTask {
#Override
public void run() {
// we don't really use the message 'what' but we have to specify something.
mHandler.sendEmptyMessage(Constants.EMPTY_MESSAGE_WHAT);
}
}
}
Create a Java class with static method startImageFallAnimation(),where you will write all your animation code and just call the method wherever it is required
The quickest solution I can think of would be to make the target Activities extend this class and change the access level of the member variables in FallAnimationActivity to 'protected'. Depending on whether you need this in all/most Activities, I'd put the logic in a base class.
have context as a parameter in your util class
example:
public animation(Imageview imageview, Context mContext)
{
Animation slideLeft = AnimationUtils.loadAnimation(mContext, R.anim.slide_out_left);
imageview.startAnimation(slideLeft);
}
then in the activity you want to call it in do
// for activity
Utils.animation(Your image view, this)
//for fragment
Utils.animation(Your image view, getContext)
my utility class is called Utils, so you type whatever you named the class and call the method accordingly

Android Creating a Seperate thread that touches Views Error [duplicate]

This question already has answers here:
Android "Only the original thread that created a view hierarchy can touch its views."
(33 answers)
Closed 8 years ago.
So I understand the error. I'm trying to adjust the UI with a thread that isn't the main UI thread. But that's inherently the problem. Doing image processing (in this case greyscaling multiple bitmaps) is a CPU intensive task. Therefore, wouldn't me trying to launch a thread that deals with image processing be the right thing to do? Or is my thought just an ideal thought that simply isn't possible because of the valid error I am receiving? Is there a work around that I'm unaware of?
Actual error message:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
//Package declaration
//Many import statements
public class PhotoViewer extends Activity implements OnClickListener {
private Button refresh_;
private Button grey_;
private ImageView image1_;
private ImageView image2_;
private ImageView image3_;
private ImageView image4_;
private GreyBitmaps gMap_;
private Bitmap bMap1_;
private Bitmap bMap2_;
private Bitmap bMap3_;
private Bitmap bMap4_;
private int num_;
private boolean makeGrey_;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photos);
// this GreyBitmaps class creates the other thread
gMap_ = new GreyBitmaps();
refresh_ = (Button) findViewById(R.id.refresh);
grey_ = (Button) findViewById(R.id.grey);
image1_ = (ImageView) findViewById(R.id.view1);
image2_ = (ImageView) findViewById(R.id.view2);
image3_ = (ImageView) findViewById(R.id.view3);
image4_ = (ImageView) findViewById(R.id.view4);
refresh_.setOnClickListener(this);
grey_.setOnClickListener(this);
makeGrey_ = false;
getPhotos();
setBitmap();
//num_ =0;
}
public void onClick(View v) {
Log.d("onClick", "Begin");
if(v == refresh_){
refreshPhoto();
}else if (v == grey_){
greyPhoto();
}
Log.d("onClick", "end");
}
protected void onResume(){
super.onResume();
gMap_.resume();
}
protected void onPause(){
super.onPause();
gMap_.pause();
}
private void refreshPhoto(){
getPhotos();
}
private void greyPhoto(){
makeGrey_ = true;
}
private void getPhotos(){
bMap1_ = BitmapFactory.decodeResource(getResources(), R.drawable.p1);
bMap2_ = BitmapFactory.decodeResource(getResources(), R.drawable.p2);
bMap3_ = BitmapFactory.decodeResource(getResources(), R.drawable.p3);
bMap4_ = BitmapFactory.decodeResource(getResources(), R.drawable.p4);
}
private void setBitmap(){
image1_.setImageBitmap(bMap1_);
image2_.setImageBitmap(bMap2_);
image3_.setImageBitmap(bMap3_);
image4_.setImageBitmap(bMap4_);
}
private Bitmap goGrey(Bitmap bmIn){
final double gs_red = 0.299;
final double gs_green = 0.587;
final double gs_blue = 0.114;
int width = bmIn.getWidth();
int height = bmIn.getHeight();
Bitmap bmOut = Bitmap.createBitmap(width, height, bmIn.getConfig());
int a, r, g, b;
int pix;
for(int x = 0; x<width; x++){
for(int y = 0; y<height; y++){
pix = bmIn.getPixel(x, y);
a = Color.alpha(pix);
r = Color.red(pix);
g = Color.green(pix);
b = Color.blue(pix);
r = g = b = (int) (gs_blue*b +gs_green*g +gs_red*r);
//write out
bmOut.setPixel(x, y, Color.argb(a, r, g, b));
}
}
return bmOut;
}
public class GreyBitmaps implements Runnable{
Thread t = null;
boolean isActive = false;
public void run() {
Log.d("Runnable", "running");
//num_ = 100;
while(isActive) {
Log.d("Runnable", "running2");
num_ = 200;
setBitmap();
try {
Thread.sleep(100);
if (makeGrey_) {
goGrey(bMap1_);
goGrey(bMap2_);
goGrey(bMap3_);
goGrey(bMap4_);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void pause(){
isActive = false;
while(true){
try{
t.join();
}catch (InterruptedException e) {
e.printStackTrace();
Log.e("Error", "Failed to join thread");
}
break;
}
t = null;
}
public void resume(){
isActive = true;
t = new Thread(this);
t.start();
}
}
}
Call your setBitmap() method in runOnUiThread thread.
See this link for runOnUiThread method implementation https://stackoverflow.com/a/11140429/4384828

In Android change a Method from Void to Return?

I'm creating a game in which I'm drawing a path that starts at the center x,y coordinates of a RelativeLayout. I'm getting the x,y coordinates, but I can't figure out how to pass the coordinates into the Path Drawing Class using my getNumbers() method. I've got this bit in the onCreate:
getNumbers();
path_em = new PathEM(this, xTint, yTint);
gBoard_RL.addView(path_em);
root_RL.addView(gBoard_RL);
and here's getNumbers():
public void getNumbers() {
gBoard_RL.getViewTreeObserver().addOnGlobalLayoutListener(NumbersoGLL);
}
OnGlobalLayoutListener NumbersoGLL = new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
xRLWInt = gBoard_RL.getWidth() / 2;
yRLHInt = gBoard_RL.getHeight() / 2;
xTint = gBoard_RL.getLeft() + xRLWInt;
yTint = gBoard_RL.getTop() + yRLHInt;
}
};
I think I have to rewrite getNumbers() so that's it's not void, but returns xTint and yTint, right? I don't know how to do that because public void onGlobalLayout() can't be changed to pass an int, when I try I get an error saying that it HAS to be void.
So basically, what I'm trying to do is in the onCreate of Game3 Class I need to get the center coordinate integers, then pass them into my Path Drawing Class. Here's the entire Game 3 Class:
public class Game3 extends Activity {
PathEM path_em;
RelativeLayout root_RL, gBoard_RL, startTimer_RL;
LayoutParams root_LP, startTimer_LP, gBoardInfo_LP, gBoard_LP, rootStartTimer_LP;
LayoutInflater LayInf = null;
View root_VUE, gBoardInfo_VUE;
TextView gameScore_TV, gameTime_TV, readyCD_TV;
FrameLayout root_FrameL;
int xScrInt, yScrInt, xRLWInt, yRLHInt, xTint, yTint;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(R.anim.cutin, R.anim.cutout);
// -- Create Root Layout
root_RL = new RelativeLayout(this);
root_LP = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
root_RL.setId(1);
root_RL.setBackgroundColor(Color.WHITE);
root_RL.setLayoutParams(root_LP);
// --- END Create Root Layout
// --- Create GameBoard
LayInf = (LayoutInflater) getApplicationContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
gBoardInfo_VUE = LayInf.inflate(R.layout.game1_info, null);
gBoardInfo_LP = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
gBoardInfo_LP.addRule(RelativeLayout.ALIGN_PARENT_TOP,
RelativeLayout.TRUE);
gBoardInfo_VUE.setId(2);
gBoardInfo_VUE.setLayoutParams(gBoardInfo_LP);
gameTime_TV = (TextView) gBoardInfo_VUE
.findViewById(R.id.game1_timeValue2_TV);
gameScore_TV = (TextView) gBoardInfo_VUE
.findViewById(R.id.game1_scoreValue2_TV);
root_RL.addView(gBoardInfo_VUE);
gBoard_RL = new RelativeLayout(this);
gBoard_LP = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
gBoard_LP.addRule(RelativeLayout.BELOW, gBoardInfo_VUE.getId());
gBoard_LP.setMargins(10, 10, 10, 10);
gBoard_RL.setLayoutParams(gBoard_LP);
gBoard_RL.setBackgroundColor(Color.BLUE);
//--- add stuff here
getNumbers();
path_em = new PathEM(this, xTint, yTint);
gBoard_RL.addView(path_em);
root_RL.addView(gBoard_RL);
root_FrameL = new FrameLayout(this);
root_FrameL.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
root_FrameL.addView(root_RL);
setContentView(root_FrameL);
// --- END Create GameBoard
}//--- END onCreate
public void getNumbers() {
gBoard_RL.getViewTreeObserver().addOnGlobalLayoutListener(NumbersoGLL);
}
OnGlobalLayoutListener NumbersoGLL = new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
xRLWInt = gBoard_RL.getWidth() / 2;
yRLHInt = gBoard_RL.getHeight() / 2;
xTint = gBoard_RL.getLeft() + xRLWInt;
yTint = gBoard_RL.getTop() + yRLHInt;
}
};
//--- PathEM Class
public class PathEM extends View {
Paint paint = new Paint();
Path path = new Path();
public PathEM(Context context, int xTint, int yTint){
super(context);
}
Pt[] thePath = { new Pt(xTint, yTint),
new Pt(200, 200),
new Pt(200, 500),
new Pt(400, 500)
};
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(7);
paint.setStyle(Paint.Style.STROKE);
path.moveTo(thePath[0].x, thePath[0].y);
for (int i = 1; i < thePath.length; i++) {
path.lineTo(thePath[i].x, thePath[i].y);
}
canvas.drawPath(path, paint);
}// --- END onDraw
class Pt {
float x, y;
Pt(float _x, float _y) {
x = _x;
y = _y;
}
}
}
}
You should put the code where you initialize the PathEM object in the onGlobalLayout() Method.
Like this:
OnGlobalLayoutListener NumbersoGLL = new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
xRLWInt = gBoard_RL.getWidth() / 2;
yRLHInt = gBoard_RL.getHeight() / 2;
xTint = gBoard_RL.getLeft() + xRLWInt;
yTint = gBoard_RL.getTop() + yRLHInt;
path_em = new PathEM(this, xTint, yTint);
gBoard_RL.addView(path_em);
root_RL.addView(gBoard_RL);
}
};
How about creating a Constants Class and setting the variable of contants variable in your onGlobalLayout() method.
That way you need not do any return.
public class Constants {
public static int value1=0;
public static int value2=0;
public static int value3=0;
public static int value4=0;
}
In your onGlobalLayout() method
Constants.value1= gBoard_RL.getWidth() / 2;
Constants.value2= gBoard_RL.getHeight() / 2;
Constants.value3= gBoard_RL.getLeft() + xRLWInt;
Constants.value4= gBoard_RL.getTop() + yRLHInt;

SherlockActionBar NullPointerException

I'm working on an android app that is a hearing test. it was quite outdated so I've had to update it. I've used the Sherlock library so the app is compatible for many different phones. What I'm trying to do is get the results of a hearing test to show up. The problem I'm getting it when I draw the graph to show the user how well they did, I'm getting a null pointer exception.
once the test is completed, the user is taken to the Saved tests Activity shown below:
public class SavedResultsActivity extends SherlockListActivity {
// TODO set column names when saving test implemented
private static final String TEST_NAME_COLUMN = ResultsDatabase.SAVED_NAME;
private static final String TEST_DATE_COLUMN = ResultsDatabase.COLUMN_NAME_CREATE_DATE;
private ResultsDatabase mDb;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDb = new ResultsDatabase(this);
setContentView(R.layout.saved_tests);
ActionBar ab = getSherlock().getActionBar();
SherlockHelper.setupActionBar(ab, this);
TextView titleText = (TextView)findViewById(R.id.title_text);
titleText.setText(R.string.Saved_Tests);
// Set the empty view
getListView().setEmptyView(findViewById(R.id.empty));
getListView().setItemsCanFocus(true);
// Get a cursor with all phones
Cursor c = getSavedTests();
if ( c != null ) {
// Set up our adapter
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.saved_results_item, c,
new String[] { TEST_NAME_COLUMN, TEST_DATE_COLUMN, TEST_DATE_COLUMN },
new int[] { android.R.id.text1, android.R.id.text2, R.id.delete_button });
adapter.setViewBinder(mViewBinder);
// Set up our adapter
setListAdapter(adapter);
}
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id)
{
Intent intent = new Intent(this, TabbedResults.class);
Cursor cursor = (Cursor) getListAdapter().getItem(position);
intent.putExtra(ResultsDatabase._ID, cursor.getInt(cursor.getColumnIndex(ResultsDatabase._ID)));
startActivity(intent);
}
private final ViewBinder mViewBinder = new SimpleCursorAdapter.ViewBinder(){
#Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if ( view.getId() == android.R.id.text1 ){
String name = cursor.getString(columnIndex);
TextView nameView = (TextView)view;
nameView.setText(name);
} else if ( view.getId() == android.R.id.text2 ){
long date = cursor.getLong(columnIndex);
String dateStr = DateUtils.formatDateTime(view.getContext(), date, DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE);
TextView dateView = (TextView)view;
dateView.setText(dateStr);
} else if ( view.getId() == R.id.delete_button ){
int idCol = cursor.getColumnIndex(ResultsDatabase._ID);
final long id = cursor.getLong(idCol);
view.setOnClickListener( new OnClickListener(){
#Override
public void onClick(View v) {
deleteTest(id);
}
});
}
return true;
}
};
private static final String DELETE_SELECTION = ResultsDatabase._ID + " = ? ";
private void deleteTest(long id) {
String[] whereArgs = new String[]{String.valueOf(id)};
SQLiteDatabase db = mDb.getWritableDatabase();
db.delete(ResultsDatabase.TABLE_NAME, DELETE_SELECTION, whereArgs);
SimpleCursorAdapter adapter = (SimpleCursorAdapter) getListAdapter();
adapter.getCursor().requery();
adapter.notifyDataSetChanged();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return MenuActivity.createMenu(this, menu);
}
// TODO fetch list of saved tests
private Cursor getSavedTests(){
// get cursor
SQLiteDatabase db = mDb.getReadableDatabase();
Cursor c = db.query(ResultsDatabase.TABLE_NAME, null, null, null, null, null,null);
startManagingCursor(c);
return c;
}
}
Here the user will click on the test they want to view and that will take the user to a tabbed results page one tab for one ear the other tab for the other ear. I've used fragments for this:
public class TabbedResults extends SherlockFragmentActivity{
TabHost mTabHost;
TabManager mTabManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_indicator);
ActionBar ab = this.getSupportActionBar();
SherlockHelper.setupActionBar(ab, this);
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
mTabHost.setup();
mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent);
mTabManager.addTab(mTabHost.newTabSpec(getString(R.string.Left_ear)).setIndicator(getString(R.string.Left_ear)),
ResultActivity.Results.class, null);
mTabManager.addTab(mTabHost.newTabSpec("contacts").setIndicator(getString(R.string.Left_ear)),
ResultActivity.Results.class, null);
if (savedInstanceState != null) {
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("tab", mTabHost.getCurrentTabTag());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return MenuActivity.createMenu(this, menu);
}
}
this method uses another method called TabManager to manage which tab is open etc:
public class TabManager extends SherlockFragmentActivity implements TabHost.OnTabChangeListener {
private final FragmentActivity mActivity;
private final TabHost mTabHost;
private final int mContainerId;
private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>();
TabInfo mLastTab;
static final class TabInfo {
private final String tag;
private final Class<?> clss;
private final Bundle args;
private Fragment fragment;
TabInfo(String _tag, Class<?> _class, Bundle _args) {
tag = _tag;
clss = _class;
args = _args;
}
}
static class DummyTabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public DummyTabFactory(Context context) {
mContext = context;
}
#Override
public View createTabContent(String tag) {
View v = new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) {
mActivity = activity;
mTabHost = tabHost;
mContainerId = containerId;
mTabHost.setOnTabChangedListener(this);
}
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
tabSpec.setContent(new DummyTabFactory(mActivity));
String tag = tabSpec.getTag();
TabInfo info = new TabInfo(tag, clss, args);
// Check to see if we already have a fragment for this tab, probably
// from a previously saved state. If so, deactivate it, because our
// initial state is that a tab isn't shown.
info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
if (info.fragment != null && !info.fragment.isDetached()) {
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
ft.detach(info.fragment);
ft.commit();
}
mTabs.put(tag, info);
mTabHost.addTab(tabSpec);
}
#Override
public void onTabChanged(String tabId) {
TabInfo newTab = mTabs.get(tabId);
if (mLastTab != newTab) {
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
if (mLastTab != null) {
if (mLastTab.fragment != null) {
ft.detach(mLastTab.fragment);
}
}
if (newTab != null) {
if (newTab.fragment == null) {
newTab.fragment = Fragment.instantiate(mActivity,
newTab.clss.getName(), newTab.args);
ft.add(mContainerId, newTab.fragment, newTab.tag);
} else {
ft.attach(newTab.fragment);
}
}
mLastTab = newTab;
ft.commit();
mActivity.getSupportFragmentManager().executePendingTransactions();
}
}
private Intent createIntent( boolean aRight) {
Intent newIntent = new Intent(getIntent());
newIntent.putExtra(ResultActivity.IS_RIGHT_EAR, aRight);
newIntent.setClass(this, ResultActivity.class);
return newIntent;
}
}
So the activity used to show the results of each ear is the results activity:
public class ResultActivity extends SherlockFragmentActivity {
public static final String IS_RIGHT_EAR = "is_right_ear";
private ArrayList<EarSrt> leftAnswerList;
private ArrayList<EarSrt> rightAnswerList;
private boolean isRightEarTab = true;
private boolean bothEarsBad;
private boolean leftEarBad;
private boolean rightEarBad;
#SuppressWarnings("unchecked")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.result);
Intent intent = getIntent();
int rowId = intent.getIntExtra(ResultsDatabase._ID, -1);
if ( rowId != -1 ) {
ResultsDatabase db = new ResultsDatabase(this);
String select = "(" + ResultsDatabase._ID + " == " + rowId + ")";
Cursor c = db.getReadableDatabase().query(ResultsDatabase.TABLE_NAME, null, select, null, null, null,null);
if ( c.moveToFirst() ) {
int leftEarColumn = c.getColumnIndex(ResultsDatabase.LEFT_EAR);
byte[] leftEarByteArray = c.getBlob(leftEarColumn);
int rightEarColumn = c.getColumnIndex(ResultsDatabase.RIGHT_EAR);
byte[] rightEarByteArray = c.getBlob(rightEarColumn);
leftAnswerList = (ArrayList<EarSrt>) ResultsDatabase.deserializeObject(leftEarByteArray);
rightAnswerList = (ArrayList<EarSrt>) ResultsDatabase.deserializeObject(rightEarByteArray);
}
} else {
byte[] leftEarByteArray = getIntent().getByteArrayExtra(ResultsDatabase.LEFT_EAR);
byte[] rightEarByteArray = getIntent().getByteArrayExtra(ResultsDatabase.RIGHT_EAR);
leftAnswerList = (ArrayList<EarSrt>) ResultsDatabase.deserializeObject(leftEarByteArray);
rightAnswerList = (ArrayList<EarSrt>) ResultsDatabase.deserializeObject(rightEarByteArray);
}
isRightEarTab = getIntent().getBooleanExtra(IS_RIGHT_EAR, true);
setResults(leftAnswerList, rightAnswerList);
if (savedInstanceState == null) {
// Do first time initialization -- add initial fragment.
Fragment newFragment = new Results();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.resultsContainer, newFragment).commit();
}
}
private float calculateAverage(List<EarSrt> steps) {
float srt = 0.0f;
int length = steps.size();
for (int i = (int)Math.ceil( (float)length/(float)2); i < length; i++) {
EarSrt es = steps.get(i);
srt += es.getSrt();
//printf("%f ," , [es srt]);
}
srt = srt / (length-(float)Math.ceil( (float)length/(float)2));
// printf("\n%f\n" , srt);
return srt;
}
private void setResults(List<EarSrt> leftEar, List<EarSrt> rightEar) {
float esLeft = calculateAverage(leftEar);
float esRight = calculateAverage(rightEar);
leftEarBad = (esLeft > 24.0);
rightEarBad = (esRight > 24.0);
bothEarsBad = (leftEarBad && rightEarBad);
setResultCaption(bothEarsBad, leftEarBad, rightEarBad);
}
/**
* TODO: this needs finishing
*/
private void setResultCaption(boolean bothEarsBad, boolean leftEarBad, boolean rightEarBad) {
TextView resultsTextView = (TextView)findViewById(R.id.results_text);
StringBuilder resultsText = new StringBuilder();
if (bothEarsBad) {
resultsText.append(getString(R.string.The_test_indicates_a_possible_hearing_loss));
resultsText.append(getString(R.string.We_recommend_that_you_visit_a_Hearing_Care_Professional_for_a_comprehensive_hearing_check));
}else{
if (leftEarBad) {
resultsText.append(getString(R.string.The_test_indicates_a_possible_hearing_loss_for_your_left_ear));
resultsText.append(getString(R.string.We_recommend_that_you_visit_a_Hearing_Care_Professional_for_a_comprehensive_hearing_check));
} else if (rightEarBad) {
resultsText.append(getString(R.string.The_test_indicates_a_possible_hearing_loss_for_your_Right_ear));
resultsText.append(getString(R.string.We_recommend_that_you_visit_a_Hearing_Care_Professional_for_a_comprehensive_hearing_check));
}else {
resultsText.append(getString(R.string.There_is_no_indication_of_hearing_loss));
}
}
resultsText.append(getString(R.string.The_results_of_the__hearing_test_are_not_to_be_utilized_as_an_official_outcome_for_assessing_levels_of_hearing_loss_True_hearing_loss_assessments_can_only_be_determined_by_a_licensed_hearing_healthcare_provider));
resultsTextView.setText(resultsText.toString());
}
public void goToLocate(View aView){
Intent locate = new Intent( this, MapActivity.class);
startActivity(locate);
finish();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
return MenuActivity.createMenu(this, menu);
}
public static class Results extends SherlockFragment{
// #Override
// public void onCreate(Bundle savedInstanceState){
// super.onCreate(savedInstanceState);
//
// }
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.results_layout, container, false);
return rootView;
}
}
}
Now this class uses the GraphView class to draw the graph:
public final class GraphView extends View {
private static final float SCALE = 0.008f; // map (min,max) to ( 0, 1)
private static final float WIDTH = 0.02f; // map (min,max) to ( 0, 1)
ArrayList<EarSrt> mPoints;
// drawing tools
private RectF rimRect;
private RectF rimRectTop;
private RectF rimRectBottom;
private float[] centreLine;
private RectF topSideBar;
private RectF bottomSideBar;
private Paint rimPaintTop;
private Paint rimPaintBottom;
private Paint outerRimPaint;
private Paint centreLinePaint;
private Paint topSideBarPaint;
private Paint bottomSideBarPaint;
private Paint titlePaint;
private Paint keyPaint;
private Paint correctPointPaint;
private Paint incorrectPointPaint;
private Paint linePaint;
private Paint pointOutlinePaint;
private Paint averagePaint;
private Paint backgroundPaint;
// end drawing tools
private Bitmap background; // holds the cached static part
private float mAverage;
public GraphView(Context context) {
super(context);
init();
}
public GraphView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public GraphView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
initDrawingTools();
}
private String getTitle() {
return getContext().getString(R.string.Normal_hearing);
}
private void initDrawingTools() {
rimRect = new RectF(0.0f, 0.0f, 1.0f, 1.0f);
rimRectTop = new RectF(0.0f, 0.5f, 1.0f, 1.0f);
rimRectBottom = new RectF(0.0f, 0.0f, 1.0f, 0.5f);
centreLine = new float[4];
centreLine[0]=0.0f;
centreLine[1]=0.5f;
centreLine[2]=1.0f;
centreLine[3]=0.5f;
topSideBar = new RectF(0.95f, 0.5f, 1.0f, 1.0f);
bottomSideBar = new RectF(0.95f, 0.0f, 1.0f, 0.5f);
// the linear gradient is a bit skewed for realism
rimPaintTop = new Paint();
rimPaintTop.setFlags(Paint.ANTI_ALIAS_FLAG);
rimPaintTop.setShader(new LinearGradient(0.40f, 0.0f, 0.60f, 1.0f,
0xff9ea3ac,
0xffc0c2c6,
TileMode.CLAMP));
rimPaintBottom = new Paint();
rimPaintBottom.setFlags(Paint.ANTI_ALIAS_FLAG);
rimPaintBottom.setShader(new LinearGradient(0.40f, 0.0f, 0.60f, 1.0f,
0xffc5cbbd,
0xff3d4649,
TileMode.CLAMP));
outerRimPaint = new Paint();
outerRimPaint.setAntiAlias(true);
outerRimPaint.setStyle(Paint.Style.STROKE);
outerRimPaint.setColor(Color.argb(0x4f, 0x33, 0x36, 0x33));
outerRimPaint.setStrokeWidth(0.001f);
centreLinePaint = new Paint();
centreLinePaint.setStyle(Paint.Style.STROKE);
centreLinePaint.setColor(0xff90cc38);
centreLinePaint.setAntiAlias(true);
centreLinePaint.setStrokeWidth(0.02f);
topSideBarPaint = new Paint();
topSideBarPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
topSideBarPaint.setShader(new LinearGradient(0.40f, 0.0f, 0.60f, 1.0f,
0xffc5cbbd,
0xff3d4649,
TileMode.CLAMP));
bottomSideBarPaint = new Paint();
bottomSideBarPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
bottomSideBarPaint.setShader(new LinearGradient(0.40f, 0.0f, 0.60f, 1.0f,
0xff4c9b3e,
0xffa0dd61,
TileMode.CLAMP));
titlePaint = new Paint();
titlePaint.setColor(0xffffffff);
titlePaint.setAntiAlias(true);
titlePaint.setTypeface(Typeface.DEFAULT_BOLD);
titlePaint.setTextAlign(Paint.Align.CENTER);
titlePaint.setTextSize(0.05f);
titlePaint.setTextScaleX(0.8f);
keyPaint = new Paint();
keyPaint.setColor(0xff000000);
keyPaint.setAntiAlias(true);
keyPaint.setTypeface(Typeface.DEFAULT_BOLD);
keyPaint.setTextAlign(Paint.Align.LEFT);
keyPaint.setTextSize(0.05f);
keyPaint.setTextScaleX(0.8f);
backgroundPaint = new Paint();
backgroundPaint.setFilterBitmap(true);
linePaint = new Paint();
linePaint.setColor(0xffffffff);
linePaint.setStrokeWidth(0);
averagePaint = new Paint();
averagePaint.setColor(0xff000000);
averagePaint.setStyle(Paint.Style.FILL);
correctPointPaint = new Paint();
correctPointPaint.setColor(0xff90cc38);
correctPointPaint.setStyle(Paint.Style.FILL);
incorrectPointPaint = new Paint();
incorrectPointPaint.setColor(0xffb1b3ba);
correctPointPaint.setStyle(Paint.Style.FILL);
pointOutlinePaint = new Paint();
pointOutlinePaint.setStyle(Paint.Style.STROKE);
pointOutlinePaint.setColor(0xffffffff);
pointOutlinePaint.setAntiAlias(true);
pointOutlinePaint.setStrokeWidth(0.0f);
}
private void drawRim(Canvas canvas) {
// first, draw the metallic body
canvas.drawRect(rimRectTop, rimPaintTop);
canvas.drawRect(rimRectBottom, rimPaintBottom);
// now the outer rim circle
canvas.drawRect(rimRect, outerRimPaint);
// Draw middleline
canvas.drawLines(centreLine, centreLinePaint);
// Draw sidebars
canvas.drawRect(topSideBar, topSideBarPaint);
canvas.drawRect(bottomSideBar, bottomSideBarPaint);
}
public void setPoints( ArrayList<EarSrt> aPoints){
mPoints = aPoints;
}
private void drawTitle(Canvas canvas) {
String title = getTitle();
canvas.drawText(title, 0.2f, 0.1f, titlePaint);
}
private void drawBackground(Canvas canvas) {
if (background == null) {
} else {
canvas.drawBitmap(background, 0, 0, backgroundPaint);
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We purposely disregard child measurements because act as a
// wrapper to a SurfaceView that centers the camera preview instead
// of stretching it.
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = (int)(width * 0.8f);
setMeasuredDimension(width, height);
}
#Override
protected void onDraw(Canvas canvas) {
drawBackground(canvas);
canvas.restore();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
regenerateBackground();
}
private void regenerateBackground() {
// free the old bitmap
if (background != null) {
background.recycle();
}
background = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas backgroundCanvas = new Canvas(background);
float scaleWidth = (float) getWidth();
float scaleHeight = (float) getHeight();
backgroundCanvas.scale(scaleWidth, scaleHeight/1.23f);
drawRim(backgroundCanvas);
drawTitle(backgroundCanvas);
drawPoints(backgroundCanvas);
drawKey(backgroundCanvas);
}
private void drawPoints(Canvas canvas) {
float gap = 1.0f/((float)mPoints.size()+2);
// Iterate though the points twice, once to
// draw the line and one to draw the points
// doesn't appear to be the most efficient
// method, but calculations of point size etc
// Draw line
int count = 1;
float prev_x = 0.0f;
float prev_y = 0.0f;
for ( EarSrt vo : mPoints){
float y_pos = 0.5f + 2*( vo.getSrt() - 24.0f)*SCALE;
float x_pos = gap*count;
if ( count != 1 ){
canvas.drawLine(prev_x, prev_y, x_pos, y_pos, linePaint);
}
count++;
prev_x = x_pos;
prev_y = y_pos;
}
// draw points
count = 1;
for ( EarSrt vo : mPoints){
float y_pos = 0.5f + 2*( vo.getSrt() - 24.0f)*SCALE;
float x_pos = gap*count;
count++;
RectF rect = new RectF(x_pos - WIDTH, y_pos - WIDTH, x_pos + WIDTH, y_pos + WIDTH);
if ( vo.isCorrect() ) {
canvas.drawRect(rect, correctPointPaint);
} else {
canvas.drawRect(rect, incorrectPointPaint);
}
canvas.drawRect(rect, pointOutlinePaint);
}
// Plot average line
float yAverage = 0.5f + 2*( mAverage - 24.0f)*SCALE;
RectF averageRect = new RectF(0.95f, yAverage - WIDTH/2.0f, 1.0f, yAverage + WIDTH/2.0f);
canvas.drawRect(averageRect, averagePaint);
}
private void drawKey(Canvas canvas) {
float rightEdge = 0.05f;
float leftEdge = 0.05f + 4 * WIDTH;
// Example correct square
RectF rect = new RectF(rightEdge, 1.1f - WIDTH, rightEdge + 2 * WIDTH, 1.1f + WIDTH);
canvas.drawRect(rect, correctPointPaint);
canvas.drawRect(rect, pointOutlinePaint);
String correctResults = getContext().getString(R.string.Correct_results);
canvas.drawText(correctResults, leftEdge, 1.1f + WIDTH, keyPaint);
// Test result line
RectF averageRect = new RectF(rightEdge, 1.2f - WIDTH/2.0f, rightEdge + 2 * WIDTH, 1.2f + WIDTH/2.0f);
canvas.drawRect(averageRect, averagePaint);
String testResults = getContext().getString(R.string.Your_test_result);
canvas.drawText(testResults, leftEdge, 1.2f + WIDTH/2.0f, keyPaint);
}
public void setAverage(float aAverage) {
mAverage = aAverage;
}
}
the issues I'm getting are on the GraphView class in the drawPoints, regenerateBackground and onSizeChanged methods.
Another issue I have is showing the correct information in the correct tab. So for one tab it only shows the results from the left are and vice versa. Any help on these issues would be massively grateful as I've been trying to get this to work for ages!!
Thanks again for any help thats given.

Categories