Android screen rotation not taking effect - android

May I check how can I rotate screen via code in Android?
The device (Android 6 ARM CPU) I am using does not have sensor to detect orientation change and I need to do it manually. The problem of this device is it will not save the setting, once I change the screen orientation via Setting menu. The next time its power on, it will go back to default "Landscape".
I tried to use below codes (one at a time) to change it, it is not working (means screen no change).
Settings.System.putInt(contentResolver, Settings.System.USER_ROTATION, 1);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
On this device, there are two options (Screen rotation and External screen rotation). I need to change both orientation to achieve what I want via Settings - Display option.
Either Kotlin or Java codes are Ok for me. Any advice?

You can't rotate android core from in you application, but you can create the custom layout in your project and controlled by your self like this :
first create custom layout :
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import android.widget.FrameLayout;
public class URotateLayout extends FrameLayout{
public static final String TAG = "URotateLayout";
public static final int ORIENTATION_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
public static final int ORIENTATION_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
public static final int ORIENTATION_SENSOR_LANDSCAPE = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
public static final int ORIENTATION_SENSOR_PORTRAIT = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
public static final int ORIENTATION_SENSOR = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
public static final int ORIENTATION_LOCKED = ActivityInfo.SCREEN_ORIENTATION_LOCKED;
private int mOrientation;
private int mLastOrientation;
private int mDefaultVideoContainerWidth;
private int mDefaultVideoContainerHeight;
private int mScreenWidth;
private int mScreenHeight;
public URotateLayout(Context context) {
super(context);
}
public URotateLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public URotateLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void updateScreenWidthAndHeight() {
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
mScreenWidth = metrics.widthPixels;
mScreenHeight = metrics.heightPixels;
}
public boolean isLandscape() {
updateScreenWidthAndHeight();
return mScreenWidth > mScreenHeight;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
updateScreenWidthAndHeight();
if (isLandscape()) {
mDefaultVideoContainerWidth = mScreenWidth;
mDefaultVideoContainerHeight = mScreenHeight;
} else {
mDefaultVideoContainerWidth = mScreenWidth;
// mDefaultVideoContainerHeight = mScreenWidth * 9 / 16;
mDefaultVideoContainerHeight=mScreenHeight;
}
setMeasuredDimension(mDefaultVideoContainerWidth, mDefaultVideoContainerHeight);
}
public int getOrientation() {
return mOrientation;
}
public void setOrientation(int orientation) {
if (getContext() instanceof Activity) {
Activity mActivity = (Activity) getContext();
switch (orientation) {
case ORIENTATION_PORTRAIT:
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case ORIENTATION_LANDSCAPE:
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case ORIENTATION_SENSOR_LANDSCAPE:
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
break;
case ORIENTATION_SENSOR_PORTRAIT:
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
break;
case ORIENTATION_SENSOR:
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
break;
case ORIENTATION_LOCKED:
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
break;
}
mOrientation = orientation;
invalidate();
}
}
public void locked() {
mLastOrientation = mOrientation;
setOrientation(ORIENTATION_LOCKED);
}
public boolean isLocked() {
return mOrientation == ORIENTATION_LOCKED ? true : false;
}
public void unlocked() {
setOrientation(mLastOrientation);
}
public void toggleOrientation() {
if (getContext() instanceof Activity && mOrientation != ORIENTATION_LOCKED) {
Activity mActivity = (Activity) getContext();
if (isLandscape()) {
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
} else {
mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
if (mOrientation == ORIENTATION_SENSOR) {
getHandler().postDelayed(new Runnable() {
#Override
public void run() {
setOrientation(mOrientation);
}
}, 2000);
}
}
}
}
Second add this to your layout, xml file like this :
<yourPackage_name.URotateLayout
android:id="#+id/rotate_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<your_layout_here/>
</yourPackage_name.URotateLayout>
finally use it in your activity or fragment like this :
//define the view i use the **butterknife**
#Bind(R.id.rotate_layout)
URotateLayout rotateLayout;
#Override
public void toggleScreenOrientation() {
if (rotateLayout != null) {
rotateLayout.toggleOrientation();
}
}
//use this for set oriention
public void setScreenOriention(int oriention) {
rotateLayout.setOrientation(oriention);
}

Related

My onDraw() method is never called

My issue is that no matter what I do, no matter how many questions and answers I read through on the internet, I cant get a simple rectangle to draw on my android device screen. Let me rephrase that, it shows up on screen but it wont change. I cant get an animation to update. onDraw() never calls multiple times, just once on startup. why? Here is my view objects code:
package prospect_industries.es;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class TestView extends View {
//Variables
public static final int SIZE = 300;
public float TOP = 0.0f;
public float LEFT = 0.0f;
public float RIGHT = 100f;
public float BOTTOM = 100f;
private Paint rectanglePaint;
private RectF rect1;
//Constructors
public TestView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
init();
}
public TestView(final Context context, final AttributeSet attrs) {
super(context, attrs, 0);
init();
}
public TestView(final Context context) {
super(context, null, 0);
init();
}
//View methods
#Override
protected void onDraw(final Canvas canvas){
canvas.drawRect(rect1, rectanglePaint);
Log.i("test1", "in onDraw");
}
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
final int chosenWidth = chooseDimension(widthMode, widthSize);
final int chosenHeight = chooseDimension(heightMode, heightSize);
setMeasuredDimension(chosenWidth, chosenHeight);
Log.i("test1", String.valueOf(chosenWidth));
Log.i("test1",String.valueOf(chosenHeight));
}
//Class Methods
private int chooseDimension(final int mode, final int size) {
switch (mode) {
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
return size;
case MeasureSpec.UNSPECIFIED:
default:
return getDefaultDimension();
}
}
private int getDefaultDimension() { return SIZE; }
private void init(){
requestFocus();
rectanglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rectanglePaint.setColor(-1);
rectanglePaint.setStyle(Paint.Style.FILL);
rect1 = new RectF(LEFT, TOP, RIGHT, BOTTOM);
}
public void update() {
RIGHT += 10;
BOTTOM += 10;
rect1 = new RectF(LEFT, TOP, RIGHT, BOTTOM);
invalidate();
Log.i("test1", "in update");
}
}
Here is my main class which has a few methods for other things Im working on as well as a timer which calls the update() method inside of my test view object.
package prospect_industries.es;
import android.app.Activity;
import android.content.Context;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends Activity {
private boolean setup = false;
public int waitDelay = 1000; //Milliseconds - currently 1 second
private Timer checkTime;
private TimerTask listen;
private MediaRecorder mRecorder;
//Splashscreen
private Timer splashScreen;
private int waitTime = 3000; //3 seconds
private GaugeView mGaugeView;
private final Random RAND = new Random();
private TestView testview;
private SurfaceHolder surfaceHolder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
//mGaugeView = (GaugeView) findViewById(R.id.gauge_view);
testview = (TestView) findViewById(R.id.test_view);
}
#Override
public void onStart() {
super.onStart();
//Timers
//1 second wait tick
checkTime = new Timer();
checkTime.schedule(new TimerTask() {
public void run() {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
//mGaugeView.setTargetValue(RAND.nextInt(101));
testview.update();
}
});
}
}, 0, waitDelay);
//Set splash screen wait timer
splashScreen = new Timer();
splashScreen.schedule(new TimerTask() {
public void run() {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
setContentView(R.layout.content_main);
}
});
splashScreen.cancel();
}
}, waitTime);
//set welcome screen
setContentView(R.layout.activity_welcome);
}
#Override
public void onStop() {
super.onStop();
if(checkTime != null) {
checkTime.cancel();
stop();
}
}
public void stop() {
if (mRecorder != null) {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
}
public double getAmplitude() {
if (mRecorder != null)
return mRecorder.getMaxAmplitude();
else
return 0;
}
public void checkSound(){
if (mRecorder == null) {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mRecorder.setOutputFile("/dev/null");
try {
mRecorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mRecorder.start();
}
}
private static class MainView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder surfaceHolder;
public MainView(Context context) {
super(context);
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
}
Lastly, here is the xml layout file which loads in the test view object.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#103681"
tools:context="prospect_industries.es.MainActivity">
<prospect_industries.es.TestView
android:layout_width="200dp"
android:layout_height="200dp"
android:id="#+id/test_view"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
I have been looking all over stackExchange for hours but I cant fix my problem, onDraw is only called once and never again no matter what I do. Right now the rectangle should be expanding out but it isnt being redrawn.
The problem is that you initialize the rectangle to be 1px wide and 1px tall and never resize it. You should be able to see 1 white pixel somewhere in the top left corner of your TestView.
Try changing the rect1 size to 0,0,100,100 and see if the problem persists.
public static final float TOP = 0.0f;
public static final float LEFT = 0.0f;
public static final float RIGHT = 100.0f;
public static final float BOTTOM = 100.0f;

How to Make FlyOutMenu so it slides from the right?

I'm trying to make sliding menu from Right side on button Click.but
in the given code it's slide from Left i change in Several method
and values but i wont get the result as i want.
I tired but Don't know where should i Change??
Help me to figure this out.
FlyOutContainer.java
package com.dell.myflyoutmenu;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;
import android.widget.Scroller;
public class FlyOutContainer extends LinearLayout {
// References to groups contained in this view.
private View menu;
private View content;
// Layout Constants
protected static final int menuMargin = 150;
public enum MenuState {
CLOSED, OPEN, CLOSING, OPENING
};
// Position information attributes
protected int currentContentOffset = 0;
protected MenuState menuCurrentState = MenuState.CLOSED;
// Animation objects
// protected Scroller menuAnimationScroller = new Scroller(this.getContext(),
// new LinearInterpolator());
protected Scroller menuAnimationScroller = new Scroller(this.getContext(),
new SmoothInterpolator());
protected Runnable menuAnimationRunnable = new AnimationRunnable();
protected Handler menuAnimationHandler = new Handler();
// Animation constants
private static final int menuAnimationDuration = 1000;
private static final int menuAnimationPollingInterval = 16;
public FlyOutContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FlyOutContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlyOutContainer(Context context) {
super(context);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
this.menu = this.getChildAt(0);
this.content = this.getChildAt(1);
this.menu.setVisibility(View.GONE);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
if (changed)
this.calculateChildDimensions();
this.menu.layout(left, top, right - menuMargin, bottom);
this.content.layout(left + this.currentContentOffset, top, right
+ this.currentContentOffset, bottom);
}
public void toggleMenu() {
switch (this.menuCurrentState) {
case CLOSED:
this.menuCurrentState = MenuState.OPENING;
this.menu.setVisibility(View.VISIBLE);
this.menuAnimationScroller.startScroll(0, 0, this.getMenuWidth(),
0, menuAnimationDuration);
break;
case OPEN:
this.menuCurrentState = MenuState.CLOSING;
this.menuAnimationScroller.startScroll(this.currentContentOffset,
0, -this.currentContentOffset, 0, menuAnimationDuration);
break;
default:
return;
}
this.menuAnimationHandler.postDelayed(this.menuAnimationRunnable,
menuAnimationPollingInterval);
this.invalidate();
}
private int getMenuWidth() {
return this.menu.getLayoutParams().width;
}
private void calculateChildDimensions() {
this.content.getLayoutParams().height = this.getHeight();
this.content.getLayoutParams().width = this.getWidth();
this.menu.getLayoutParams().width = this.getWidth() - menuMargin;
this.menu.getLayoutParams().height = this.getHeight();
}
private void adjustContentPosition(boolean isAnimationOngoing) {
int scrollerOffset = this.menuAnimationScroller.getCurrX();
this.content.offsetLeftAndRight(scrollerOffset
- this.currentContentOffset);
this.currentContentOffset = scrollerOffset;
this.invalidate();
if (isAnimationOngoing)
this.menuAnimationHandler.postDelayed(this.menuAnimationRunnable,
menuAnimationPollingInterval);
else
this.onMenuTransitionComplete();
}
private void onMenuTransitionComplete() {
switch (this.menuCurrentState) {
case OPENING:
this.menuCurrentState = MenuState.OPEN;
break;
case CLOSING:
this.menuCurrentState = MenuState.CLOSED;
this.menu.setVisibility(View.GONE);
break;
default:
return;
}
}
protected class SmoothInterpolator implements Interpolator{
#Override
public float getInterpolation(float t) {
return (float)Math.pow(t-1, 5) + 1;
}
}
protected class AnimationRunnable implements Runnable {
#Override
public void run() {
FlyOutContainer.this
.adjustContentPosition(FlyOutContainer.this.menuAnimationScroller
.computeScrollOffset());
}
}
}

Send Value to Main from extended View

I have this activity that detects Multi-Touch and counts each instance that the device is tapped over 3 times. What I want is to do a check in Main to see if it reaches the limit that have been set.
Main Activity
package com.test.multitouch;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// DETECT more than 20 counts here and display a toast
}
Custom View which extends view
package com.test.multitouch;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
#SuppressLint("ClickableViewAccessibility")
public class custom_view extends View {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
final int MAX_NUMBER_OF_POINT = 4;
float[] x = new float[MAX_NUMBER_OF_POINT];
float[] y = new float[MAX_NUMBER_OF_POINT];
boolean[] touching = new boolean[MAX_NUMBER_OF_POINT];
int count = 0;
long cur = System.currentTimeMillis();
long dur = 30000;
long fut = cur + dur;
public custom_view(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public custom_view(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public custom_view(Context context) {
super(context);
init();
}
void init() {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(40);
}
#Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i < MAX_NUMBER_OF_POINT; i++) {
if (touching[i]) {
switch (i) {
case 1:
paint.setColor(Color.BLUE);
break;
case 2:
paint.setColor(Color.RED);
break;
case 3:
paint.setColor(Color.YELLOW);
break;
case 4:
paint.setColor(Color.GREEN);
break;
}
canvas.drawCircle(x[i], y[i], 70f, paint);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = (event.getAction() & MotionEvent.ACTION_MASK);
int pointCount = event.getPointerCount();
if (pointCount > 3) {
Log.i("LOG", "register multi touch");
count++;
if (count > 20) {
//SEND BACK TO MAIN TO SAY IT HAS BEEN ACHIEVED
}
}
for (int i = 0; i < pointCount; i++) {
int id = event.getPointerId(i);
if (id < MAX_NUMBER_OF_POINT) {
x[id] = (int) event.getX(i);
y[id] = (int) event.getY(i);
if ((action == MotionEvent.ACTION_DOWN)
|| (action == MotionEvent.ACTION_POINTER_DOWN)
|| (action == MotionEvent.ACTION_MOVE)) {
touching[id] = true;
} else {
touching[id] = false;
}
}
}
invalidate();
return true;
}
}
Your custom view has a reference to the context it's attached to. I assume this view is running in the same activity you are trying to reference. You can get the reference to the activity as follows:
MainActivity mainActivity = (MainActivity) custom_view.this.getContext();
I also assumed you are calling this from inside your onTouchListener. You need to reference the "this" to get to the outterclass instance, otherwise this will refer to the instance of your onTouchListener class instead. Also, you should capitalize class names, so you can recognize from the capitalization whether we are referring to an instance or class definition.
Once you have the reference, you can call some function on main Activity to update it.
mainActivity.callSomeFunction();

How do I draw a drawable with its exact size in my custom view?

SOLVED: Solution below as answer.
I have a custom view with a TransitionDrawable and when I draw it in the onDraw() method it scales automatically to fill the whole parent layout, even when it's set in the xml to wrap_content. The picture is in mdpi and hdpi and my testing device (samsung galaxy s) I think it's no more than hdpi.
package com.adyrsoft.pronunciationtrainer;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.TransitionDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class RecordButton extends View {
private static final String TAG = "RecordButton";
private TransitionDrawable mDrawable;
private boolean mActivated;
private OnClickListener mOnClickListenerInternal = new OnClickListener() {
#Override
public void onClick(View v) {
toggleState();
if(mOnClickListener != null) {
mOnClickListener.onClick(v);
}
}
};
private OnClickListener mOnClickListener = null;
public RecordButton(Context context) {
super(context);
init();
}
public RecordButton(Context context, AttributeSet attrib) {
super(context, attrib);
init();
}
public RecordButton(Context context, AttributeSet attrib, int defStyle) {
super(context, attrib, defStyle);
init();
}
public void setState(boolean activated) {
mActivated = activated;
if(mActivated){
mDrawable.startTransition(300);
}
else {
mDrawable.reverseTransition(300);
}
}
public void toggleState() {
if(mActivated) {
setState(false);
}
else {
setState(true);
}
}
#SuppressWarnings("deprecation")
private void init() {
mActivated = false;
mDrawable = (TransitionDrawable) getResources().getDrawable(R.drawable.btnrecord);
Log.d(TAG, "Drawable intrinsic width and height are: " +
Integer.toString(mDrawable.getIntrinsicWidth()) + " " +
Integer.toString(mDrawable.getIntrinsicHeight()));
mDrawable.setBounds(0,0,mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
Log.d(TAG, "The bounds for the button are: "+mDrawable.getBounds().flattenToString());
super.setBackgroundDrawable(mDrawable);
setClickable(true);
super.setOnClickListener(mOnClickListenerInternal);
invalidate();
}
public void setOnClickListener(View.OnClickListener listener) {
mOnClickListener = listener;
}
protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
}
}
What am I doing wrong?
Thanks.
After hours trying to understand how I should use the drawables in a custom view in order to be displayed in its original size, I've figured out how to do it.
First a few things that I didn't know but are a must is:
The background drawable should be left to the parent class to be
drawn when using View as the parent. If not, the TransitionDrawable can't be seen fading between pictures.
Only if I am going to draw on the background drawable I should override onDraw() and do the drawing there.
And the last but not less important is that I should override onMeasure() to specify the size of the view. If I don't do it, it will fill all the free space in the parent layout, as it was happening to me.
I've passed the TransitionDrawable to the parent class with setBackgroundDrawable() and since I wasn't drawing in the background drawable, I've removed the onDraw() method. Also I've implemented onMeasure() with a quick and dirty solution specifying the size of the picture I am drawing.
This is the final result:
public class RecordButton extends View {
private static final String TAG = "RecordButton";
private static final int DESIRED_WIDTH = 180;
private static final int DESIRED_HEIGHT = 66;
private TransitionDrawable mDrawable;
private Rect mViewRect;
private boolean mActivated;
private OnClickListener mOnClickListenerInternal = new OnClickListener() {
#Override
public void onClick(View v) {
toggleState();
if(mOnClickListener != null) {
mOnClickListener.onClick(v);
}
}
};
private OnClickListener mOnClickListener = null;
public RecordButton(Context context) {
this(context, null, 0);
}
public RecordButton(Context context, AttributeSet attrib) {
this(context, attrib, 0);
}
public RecordButton(Context context, AttributeSet attrib, int defStyle) {
super(context, attrib, defStyle);
init();
}
public void setState(boolean activated) {
mActivated = activated;
if(mActivated){
mDrawable.startTransition(300);
}
else {
mDrawable.reverseTransition(300);
}
}
public void toggleState() {
if(mActivated) {
setState(false);
}
else {
setState(true);
}
}
#SuppressWarnings("deprecation")
private void init() {
mActivated = false;
mDrawable = (TransitionDrawable) getResources().getDrawable(R.drawable.btnrecord);
setBackgroundDrawable(mDrawable);
setClickable(true);
super.setOnClickListener(mOnClickListenerInternal);
invalidate();
}
public void setOnClickListener(View.OnClickListener listener) {
mOnClickListener = listener;
}
#Override
protected void onMeasure(int m, int n) {
setMeasuredDimension(DESIRED_WIDTH, DESIRED_HEIGHT);
}
}

Custom layout with WindowManager

For some reason, I keep getting an Error inflating Class message because I'm trying to implement
Caused by: java.lang.NullPointerException
at pap.crowslanding.GameView.(GameView.java:49)
Line 49 is this
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
I am doing it this way because I am not in an Activity, any suggestions?
EDIT:
public class GameView extends SurfaceView {
static final long FPS = 10;
public Bitmap bmp;
public SurfaceHolder holder;
public LoopGameThread loopGameThread;
public static Sprite sprite;
public LayoutInflater inflater;
//maze variables
public int width;
public int height;
private float cellWidth;
private boolean[][] north; // is there a wall to north of cell i, j
private boolean[][] east;
private boolean[][] south;
private boolean[][] west;
private boolean[][] visited;
private double size;
boolean done = false;
Display display = new
Paint paint = new Paint();
//maze variables
public GameView(Context context) {
super(context);
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point screenSize = new Point();
display.getSize(screenSize);
int width = screenSize.x;
int height = screenSize.y;
}
public GameView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
//maze variables
initVars(attrs);
initMaze();
generate(1, 1);
//maze variables
loopGameThread = new LoopGameThread(this);
holder = getHolder();
holder.addCallback(new Callback() {
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
loopGameThread.isStart(true);
loopGameThread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.crow);
sprite = new Sprite(this, bmp);
}
//MAZE VARIABLES
private void initVars(AttributeSet attrs) {
//requires display variables
}
Then within my initVars, I need to use those display variables
EDIT 2 :
package pap.crowslanding;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnTouchListener;
import android.widget.Button;
public class Game extends MainActivity{
static boolean pressedUp = false;
protected static GameView gameV;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.tester1);
Button moveLeft = (Button) findViewById(R.id.button1);
gameV = (GameView)findViewById(R.id.game_view);
moveLeft.setOnTouchListener(new View.OnTouchListener() {
private Handler mHandler;
#Override public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mHandler != null) return true;
mHandler = new Handler();
mHandler.postDelayed(mAction, 100);
break;
case MotionEvent.ACTION_UP:
if (mHandler == null) return true;
mHandler.removeCallbacks(mAction);
mHandler = null;
break;
}
return false;
}
Runnable mAction = new Runnable() {
#Override public void run() {
System.out.println("Performing action...");
mHandler.postDelayed(this, 100);
GameView.sprite.movementGo();
}
};
});
}
}
You need to pass your context down to whatever class is calling this function.
You could for example, keep local context value in your class which you can refer to in your functions. First, you'll need to make a constructor which will pass in a context to your class to use.
public class Example {
Context mContext;
public Example(Context mContext;){
this.mContext = mContext;
}
public someFunction(){
...
WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
...
}
}
In your Activity class that creates an instance of your class and uses it, you'll need to pass in the Activity's context like so:
public class SomeActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Example test = new Example(this); //You are passing in the Activity as the context here
test.someFunction();
}
}
EDIT to your edit:
Create a new local variable in your GameView class:
private Context mContext;
Then assign a value to mContext in your GameView constructor like so:
public GameView(Context context) {
super(context);
mContext = context;
...
}
You can now use mContext inside of your initVars() function

Categories

Resources