I want to display the compass(Image View) on device at a specific location.I tried Like this below code to display the compass view on device but the thing is i need to display at Specific location and small view only but it occupies entire screen space.Can you help me to fix an compass image at specific location.Using this line of code i am getting an image form Drawable folder. this.setImageResource(R.drawable.compassrose); So how to fix that image at specific location.
Class1:-
public class Compass extends Activity implements SensorListener {
SensorManager sensorManager;
static final int sensor = SensorManager.SENSOR_ORIENTATION;
Rose rose;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//http://ofps.oreilly.com/titles/9781449390501/Android_System_Services.html
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
//FLAG_FULLSCREEN
//FLAG_SCALED
rose = new Rose(this);
setContentView(rose);
// get sensor manager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
// register to listen to sensors
#Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this, sensor);
}
// unregister
#Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
// Ignore for now
public void onAccuracyChanged(int sensor, int accuracy) {
}
// Listen to sensor and provide output
public void onSensorChanged(int sensor, float[] values) {
if (sensor != Compass.sensor)
return;
int orientation = (int) values[0];
rose.setDirection(orientation);
}
}
Class 2:-
public class Rose extends ImageView {
Paint paint;
int direction = 0;
public Rose(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStrokeWidth(2);
paint.setStyle(Style.STROKE);
this.setImageResource(R.drawable.compassrose);
}
#Override
public void onDraw(Canvas canvas) {
int height = this.getHeight();
int width = this.getWidth();
canvas.rotate(direction, width / 2, height / 2);
super.onDraw(canvas);
}
public void setDirection(int direction) {
this.direction = direction;
this.invalidate();
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
rose = new Rose(this);
txtorientation = (TextView) findViewById(R.id.textView1);
compassLayout = (RelativeLayout)findViewById(R.id.CompassLayout);
compassLayout.addView(rose);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
Log.d("Compass", "onCreated");
}
Are you asking how to position an ImageView in an Android layout? Have you tried with XML, or does it need to be set programmatically?
If you are just trying to position an ImageView, then try going through some of the layout tutorials: http://developer.android.com/resources/tutorials/views/index.html
If not, then please add more detail to your question
Related
my app shows a bunch of bitmaps that animate one by one as it's stored in a Bitmap array and initially when app starts up curPosition is 0 to start animating obj at index 0. The handleMessage will animate each obj with a 1000ms delay between each obj when app starts up first time and so when app starts up first time handleMessage animates each obj normally.
The issue is once I double tap the restart button bitmap. I used the GestureDetector class and I have a Restart button constructed via a bitmap that when I listen for onDoubleTap and what should happen is the handleMessage will go thru each bitmap restarting animating them.
For some reason, when I double tap the Restart button bitmap, the handleMessage is running and i know this since I put in a logcat message and for that logcat message in update method I see it running thru each curPosition so I mean this line: Log.i ("cur pos. so far:", "" + curPosition );
but I don't visually see the animation running thru update method unless I interrupt app (i.e. close app OR minimize then resume app) and double tap the Restart button bitmap and the double tapping Restart button bitmap WORKS ONLY ONCE so I need to interrupt app to get it to work again.
public class MainActivity extends Activity implements
GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener {
private MySurfaceView mysurfaceView;
private Bitmap restart_buttonBitmap;
private GestureDetector mGestureDetector;
private MiniProj2Button restart;
private MiniProj2Button newLevel;
private final int SIZE = 5;
private final int DELAY = 1000;
private Bitmap[] myObjs = new Bitmap[ SIZE ];
//Screen size info
private int screenWidth;
private int screenHeight;
//The size in pixels of a place on the game board
private int blockSize;
private int numBlocksWide;
private int numBlocksHigh;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mySurfaceView = new MySurfaceView(this);
setContentView(mySurfaceView);
// Create a GestureDetector
mGestureDetector = new GestureDetector(this, this);
// Attach listeners that'll be called for double-tap and related gestures
mGestureDetector.setOnDoubleTapListener( this );
}//END METHOD: onCreate
#Override
protected void onStop() {
super.onStop();
Log.d("onStop", "Main Activity's onStop called");
gameView.surfaceDestroyed( mySurfaceView.getHolder() );
this.finish();
}
#Override
protected void onResume() {
super.onResume();
Log.d("onResume", "Main Activity's onResume called");
mySurfaceView = new MySurfaceView(this);
setContentView(mySurfaceView);
mySurfaceView.surfaceCreated( mySurfaceView.getHolder() );
}
#Override
protected void onPause() {
super.onPause();
Log.i("onPause", "Main Activity's onPause called");
mySurfaceView.surfaceDestroyed( mySurfaceView.getHolder() );
}
#Override
public boolean onDoubleTap(MotionEvent e) {
//reset animation if Restart button pressed!
if ( restart.isButtonTouched(e.getX(), e.getY(), blockSize,blockSize) ) {
curPosition = 0;
}
return true;
}
public void configureDisplay() {
//find out the width and height of the screen
Display display =
getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
//Determine the size of each block/place on the board
// blockSize = screenWidth/10;
blockSize = screenWidth/10;
//Determine how many blocks will fit into the
//height and width
// numBlocksWide = 10;
numBlocksWide = 10;
numBlocksHigh = ( ( screenHeight ) ) / blockSize;
}//END METHOD: configureDisplay
#Override
public boolean onTouchEvent(MotionEvent e) {
mGestureDetector.onTouchEvent(e);
return super.onTouchEvent(e);
}//END onTouchEvent
class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Handler.Callback {
Canvas canvas = new Canvas();
SurfaceHolder surfaceHolder;//this lets us access the canvas but still need to use Canvas class
Handler myHandler;
Paint paint = new Paint ();
public MySurfaceView(Context context) {
super(context);
paint.setColor(Color.argb(255, 0, 0, 0));
path = new Path ();
myHandler = new Handler(this);
getHolder().addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
this.surfaceHolder = holder;
myHandler.sendEmptyMessage(0);
}
#Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
// What do I enter here???
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("Me", "surfaceDestroyed: bye!" );
myHandler.removeCallbacksAndMessages(null);
}
protected void drawIt ( ) {
if ( surfaceHolder.getSurface().isValid() ) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);//the background
//for each obj, draw it
surfaceHolder.unlockCanvasAndPost(canvas);
}//END IF BLOCK: For valid surfaceHolder
}//END METHOD: drawIt
public void update() {
Log.i ("cur pos. so far:", "" + curPosition );
if ( curPosition < SIZE ) {
myObjs [ curPosition ].animateMe ( );
curPosition++;
}
}//END METHOD: update
#Override
public boolean handleMessage(Message msg) {
if (curPosition < SIZE ) {
Log.i("Still objs 2 animate","Yes");
Log.i ("cur pos. so far:", "" + curPosition );
gameView.update();
gameView.drawIt();
myHandler.sendEmptyMessageDelayed(msg.what, DELAY);
}
else {
myHandler.sendEmptyMessageDelayed(msg.what, 10);
gameView.drawIt();
}
return true;
}//END METHOD: handleMessage
}//END INNER CLASS: MySurfaceView
}//END CLASS: MainActivity
If the user turns over the phone I want to react to that by stopping my text to speech reading. It would be a nice feature for my app, but how can I detect this motion? I'm not really familiar with motion sensors and I could not find this specific motion listener anywhere, mostly just screen orientations. Thanks for the help!
This sample activity demonstrates how a device's gravity sensor can be used to detect when the device is turned over. In method onSensorChanged(), term factor determines how complete the "turn over" must be. Typical range might be 0.7 to 0.95.
Support for Gravity Sensor was added in Android API 9. Not all devices have a gravity sensor.
public class MainActivity extends AppCompatActivity implements SensorEventListener {
private static final String TAG = "Demo";
private SensorManager mSensorManager;
private Sensor mGravitySensor;
private boolean mFacingDown;
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// nothing
}
#Override
public void onSensorChanged(SensorEvent event) {
final float factor = 0.95F;
if (event.sensor == mGravitySensor) {
boolean nowDown = event.values[2] < -SensorManager.GRAVITY_EARTH * factor;
if (nowDown != mFacingDown) {
if (nowDown) {
Log.i(TAG, "DOWN");
} else {
Log.i(TAG, "UP");
}
mFacingDown = nowDown;
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mGravitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
if (mGravitySensor == null) {
Log.w(TAG, "Device has no gravity sensor");
}
}
#Override
protected void onResume() {
super.onResume();
if (mGravitySensor != null) {
mSensorManager.registerListener(this, mGravitySensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
#Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
}
I created a view from ImageView. this imageview is a ball on screen(Depending on the acceleration sensor). now how can i do getting current positon it on the screen ?because I don't want the ball be out of the screen. like :
All my code :
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
AnimatedView animatedView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
animatedView = new AnimatedView(this);
setContentView(animatedView);
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x -= ((int) event.values[0])*4;
y += ((int) event.values[1])*4;
}
}
public class AnimatedView extends ImageView {
static final int width = 100;
static final int height = 100;
public AnimatedView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xffffAC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
#Override
protected void onDraw(Canvas canvas) {
mDrawable.setBounds(x, y, x + width, y + height);
mDrawable.draw(canvas);
invalidate();
}
}
}
other question,
Which one is better to use?TYPE_ACCELEROMETER or TYPE_GRAVITY?
I want to support more devices.
You already know the position, which is your x and y.
What you need to do is to stop these values from falling of the screen.
First, get the size of your screen:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
now size holds the screenSize.
Then add the following to your method
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x -= ((int) event.values[0])*4;
y += ((int) event.values[1])*4;
if(x < 0)
x = 0;
else if(x > size.x)
x = size.x
if(y < 0)
y = 0;
else if (y > size.y)
y = size.y
}
I would also recomend that you use a thread to handle the x and y position. You can control how often a thread will run, the sensor will trigger every time an event happens.
For a better understanding of the Android Sensors, read this: http://www.codeproject.com/Articles/729759/Android-Sensor-Fusion-Tutorial
Some sensors are hardware sensors, others are software sensors that combine hardware sensors.
In your case: Im not sure what the purpose of your app is, but I guess that you want to move the ball by tilting the screen. I would say that GRAVITY works perfectly for that.
You can retrieve the location of a view by calling the getTop() and getLeft() functions which return x and y coordinates respectively, reference: http://developer.android.com/reference/android/view/View.html#Position
Choosing the type depends on the goal offcourse, using Acceleromtere means measuring the acceleration of the device whilst gravity measures the gravitational force on the device.
Please note that acceleromter values include gravity values as mentioned here: http://developer.android.com/guide/topics/sensors/sensors_motion.html
I personally would suggest using Accelerometer or the Gyroscope. The gyroscope doesn't use acceleration but the actual orientation of the device in space, which might be what you are actually looking for.
i have two isses
- the ball is going out of bound of the screen
- the ball movement is not smooth ( looks it disappears and re appears on the screen)
here is my code
public class GameActivity extends Activity{
private GameView GameView;
private SensorManager sensorManager;
private Sensor accelerometer;
public static Timer tmr;
public static TimerTask tsk = null;
public static Handler handler = new Handler();
public static Runnable runnable;
int mScrWidth, mScrHeight;
android.graphics.PointF mBallPos, mBallSpd;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(0xFFFFFFFF,LayoutParams.FLAG_FULLSCREEN||LayoutParams.FLAG_KEEP_SCREEN_ON);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
GameView = (GameView) findViewById(R.id.gameView);
// Add sensor listener
// Set the screen always portrait
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
// get screen dimensions
Display display = getWindowManager().getDefaultDisplay();
mScrWidth = display.getWidth();
mScrHeight = display.getHeight();
mBallPos = new android.graphics.PointF();
mBallSpd = new android.graphics.PointF();
// create variables for ball position and speed
mBallPos.x = mScrWidth / 2;
mBallPos.y = mScrHeight / 2;
mBallSpd.x = 0;
mBallSpd.y = 0;
// listener for accelerometer, use anonymous class for simplicity
((SensorManager) getSystemService(Context.SENSOR_SERVICE))
.registerListener(new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
// set ball speed based on phone tilt (ignore Z axis)
mBallSpd.x =-event.values[0];
mBallSpd.y = event.values[1];
// timer event will redraw ball
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
} // ignore this event
}, ((SensorManager) getSystemService(Context.SENSOR_SERVICE))
.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0),
SensorManager.SENSOR_DELAY_NORMAL);
}
}
I have seen a few code examples of 1.0 / 1.1 but since a lot of that is deprecated now I was hoping to find a nice 1.5+ example. I have some code here that I wrote but it doesn't really work properly. Any help would be great, thanks!
public class collectAccel extends Activity implements SensorEventListener,
OnClickListener{
private SensorManager sensorMgr;
private TextView xLabel, yLabel, zLabel;
private Button StartBtn;
private List<Sensor> sensorList;
private float x, y, z;
private long lastUpdate = -1;
// deltas for calibration
private float cx, cy, cz;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
xLabel = (TextView) findViewById(R.id.x_label);
yLabel = (TextView) findViewById(R.id.y_label);
zLabel = (TextView) findViewById(R.id.z_label);
StartBtn = (Button) findViewById(R.id.Button1);
StartBtn.setOnClickListener(this);
}
#Override
public void onClick(View arg0) {
if (xLabel.getVisibility() != 1)
xLabel.setVisibility(1);
if (yLabel.getVisibility() != 1)
yLabel.setVisibility(1);
if (zLabel.getVisibility() != 1)
zLabel.setVisibility(1);
}
#Override
protected void onPause() {
super.onPause();
sensorMgr.unregisterListener((SensorEventListener)this, sensorList.get(0));
sensorMgr = null;
cx = 0;
cy = 0;
cz = 0;
}
#Override
protected void onResume() {
super.onResume();
sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorList = sensorMgr.getSensorList(Sensor.TYPE_ACCELEROMETER);
boolean accelSupported = sensorMgr.registerListener((SensorEventListener)this,
sensorList.get(0),
SENSOR_DELAY_UI);
if (!accelSupported) {
// on accelerometer on this device
sensorMgr.unregisterListener((SensorEventListener)this, sensorList.get(0));
}
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
cx = 0;
cy = 0;
cz = 0;
}
#Override
public void onSensorChanged(SensorEvent arg0) {
if (arg0.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
long curTime = System.currentTimeMillis();
// only allow one update every 100ms, otherwise updates
// come way too fast and the phone gets bogged down
// with garbage collection
if (lastUpdate == -1 || (curTime - lastUpdate) > 100) {
lastUpdate = curTime;
x = arg0.values[0];
y = arg0.values[1];
z = arg0.values[2];
xLabel.setText(String.format("X: %+2.5f (%+2.5f)", (x+cx), cx));
yLabel.setText(String.format("Y: %+2.5f (%+2.5f)", (y+cy), cy));
zLabel.setText(String.format("Z: %+2.5f (%+2.5f)", (z+cz), cz));
}
}
}
}
You can look it up in the Android Reference but It looks like you'll need
SensorManager mgr = Context.getSystemService(SENSOR_SERVICE);
IList<Sensor> sensorList = mgr.getSensorList(SensorManager.SENSOR_ACCELEROMETER);
If you really want the list, but I think you are actually meant to use SensorManager.RegisterListener(SensorListener listener, int sensors, int rate) or another version of that method.