I am android developer .I create system window overlay .I want to bounce bubble only stay left top corner, right top corner,bottom left corner.bottom right corner .you stretch ball from top right corner to center then ball direct bounce top right corner .ball just stay only four corner like Facebook messenger . i also try some days but i don't know to do this.here is my code any one please tell what is change in this code.
package com.example.bubble;
import java.io.IOException;
import java.io.InputStream;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.os.Handler;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.RelativeLayout;
#SuppressWarnings("deprecation")
public class PlayerService extends Service
{
private static final int HIDDEN_FRACTION = 20; // Controls fraction of the tray hidden when open
private static final int MOVEMENT_REGION_FRACTION = 20; // Controls fraction of y-axis on screen within which the tray stays.
private static final int VIEW_CROP_FRACTION = 12; // Controls fraction of the tray chipped at the right end.
private static final int ANIMATION_FRAME_RATE = 30; // Animation frame rate per second.
private static final int VIEW_DIM_X_DP = 170; // Width of the tray in dps
private static final int VIEW_DIM_Y_DP = 170; // Height of the tray in dps
// Layout containers for various widgets
private WindowManager mWindowManager; // Reference to the window
private WindowManager.LayoutParams mWindowParams; // Parameters of the root layout
private RelativeLayout mRootLayout; // Root layout
private RelativeLayout mCoverLayout; // Contains album cover of the active song
// Variables that control drag
private int mStartDragX;
//private int mStartDragY; // Unused as yet
private int mPrevDragX;
private int mPrevDragY;
private boolean mIsTrayOpen = true;
// Controls for animations
private Timer mTrayAnimationTimer;
private TrayAnimationTimerTask mTrayTimerTask;
private Handler mAnimationHandler = new Handler();
#Override
public IBinder onBind(Intent intent) {
// Not used
return null;
}
#Override
public void onCreate() {
// Get references to all the views and add them to root view as needed.
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mRootLayout = (RelativeLayout) LayoutInflater.from(this).
inflate(R.layout.service_player, null);
mCoverLayout = (RelativeLayout) mRootLayout.findViewById(R.id.cover_layout);
mCoverLayout.setOnTouchListener(new TrayTouchListener());
mWindowParams = new WindowManager.LayoutParams(
Utils.dpToPixels(VIEW_DIM_X_DP, getResources()),
Utils.dpToPixels(VIEW_DIM_Y_DP, getResources()),
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
PixelFormat.TRANSLUCENT);
mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;
mWindowManager.addView(mRootLayout, mWindowParams);
// Post these actions at the end of looper message queue so that the layout is
// fully inflated once these functions execute
mRootLayout.postDelayed(new Runnable() {
#Override
public void run() {
// Reusable variables
RelativeLayout.LayoutParams params;
InputStream is;
Bitmap bmap;
int containerNewWidth = (VIEW_CROP_FRACTION-1)*mCoverLayout.getHeight()/VIEW_CROP_FRACTION;
// Setup background album cover
is=null;
try {
//is = getAssets().open(mPlaylist.getCurrentSongInfo().mAlbumCoverPath);
is=getAssets().open("adele.png");
} catch (IOException e) {
e.printStackTrace();
}
bmap = Utils.loadMaskedBitmap(is, mCoverLayout.getHeight(), containerNewWidth);
params = (RelativeLayout.LayoutParams) mCoverLayout.getLayoutParams();
params.width = (bmap.getWidth() * mCoverLayout.getHeight()) / bmap.getHeight();
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,0);
mCoverLayout.setLayoutParams(params);
mCoverLayout.requestLayout();
mCoverLayout.setBackgroundDrawable(new BitmapDrawable(getResources(), bmap));
// Setup the root layout
mWindowParams.x = -mCoverLayout.getLayoutParams().width;
mWindowParams.y = (getApplicationContext().getResources().getDisplayMetrics().heightPixels-mRootLayout.getHeight()) / 2;
mWindowManager.updateViewLayout(mRootLayout, mWindowParams);
// Make everything visible
mRootLayout.setVisibility(View.VISIBLE);
// Animate the Tray
mTrayTimerTask = new TrayAnimationTimerTask();
mTrayAnimationTimer = new Timer();
mTrayAnimationTimer.schedule(mTrayTimerTask, 0, ANIMATION_FRAME_RATE);
}
}, ANIMATION_FRAME_RATE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getBooleanExtra("stop_service", false)){
// If it's a call from the notification, stop the service.
stopSelf();
}else{
// Make the service run in foreground so that the system does not shut it down.
Intent notificationIntent = new Intent(this, PlayerService.class);
notificationIntent.putExtra("stop_service", true);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, notificationIntent, 0);
Notification notification = new Notification(
R.drawable.ic_launcher,
"Spotify tray launched",
System.currentTimeMillis());
notification.setLatestEventInfo(
this,
"Spotify tray",
"Tap to close the widget.",
pendingIntent);
startForeground(86, notification);
}
return START_STICKY;
}
// The app is closing.
#Override
public void onDestroy() {
if (mRootLayout != null)
mWindowManager.removeView(mRootLayout);
}
// Drags the tray as per touch info
private void dragTray(int action, int x, int y){
switch (action){
case MotionEvent.ACTION_DOWN:
// Cancel any currently running animations/automatic tray movements.
if (mTrayTimerTask!=null){
mTrayTimerTask.cancel();
mTrayAnimationTimer.cancel();
}
// Store the start points
mStartDragX = x;
//mStartDragY = y;
mPrevDragX = x;
mPrevDragY = y;
break;
case MotionEvent.ACTION_MOVE:
// Calculate position of the whole view according to the drag, and update layout.
float deltaX = x-mPrevDragX;
float deltaY = y-mPrevDragY;
mWindowParams.x += deltaX;
mWindowParams.y += deltaY;
mPrevDragX = x;
mPrevDragY = y;
mWindowManager.updateViewLayout(mRootLayout, mWindowParams);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// When the view is released, bring it back to "open" or "closed" state.
if ((mIsTrayOpen && (x-mStartDragX)<=0) ||
(!mIsTrayOpen && (x-mStartDragX)>=0))
mIsTrayOpen = !mIsTrayOpen;
mTrayTimerTask = new TrayAnimationTimerTask();
mTrayAnimationTimer = new Timer();
mTrayAnimationTimer.schedule(mTrayTimerTask, 0, ANIMATION_FRAME_RATE);
break;
}
}
// Listens to the touch events on the tray.
private class TrayTouchListener implements OnTouchListener {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// Filter and redirect the events to dragTray()
dragTray(action, (int)event.getRawX(), (int)event.getRawY());
break;
default:
return false;
}
return true;
}
}
// Timer for animation/automatic movement of the tray.
private class TrayAnimationTimerTask extends TimerTask{
// Ultimate destination coordinates toward which the tray will move
int mDestX;
int mDestY;
public TrayAnimationTimerTask(){
// Setup destination coordinates based on the tray state.
super();
if (!mIsTrayOpen){
mDestX = -mCoverLayout.getWidth();
}else{
mDestX = -mRootLayout.getWidth()/HIDDEN_FRACTION;
}
// Keep upper edge of the widget within the upper limit of screen
int screenHeight = getResources().getDisplayMetrics().heightPixels;
mDestY = Math.max(
screenHeight/MOVEMENT_REGION_FRACTION,
mWindowParams.y);
// Keep lower edge of the widget within the lower limit of screen
mDestY = Math.min(
((MOVEMENT_REGION_FRACTION-1)*screenHeight)/MOVEMENT_REGION_FRACTION - mRootLayout.getWidth(),
mDestY);
mDestX = Math.max(mWindowParams.x,screenHeight/MOVEMENT_REGION_FRACTION);
// Keep lower edge of the widget within the lower limit of screen
mDestX = Math.min(mDestX,((MOVEMENT_REGION_FRACTION-1)*screenHeight)/MOVEMENT_REGION_FRACTION - mRootLayout.getWidth());
}
// This function is called after every frame.
#Override
public void run() {
// handler is used to run the function on main UI thread in order to
// access the layouts and UI elements.
mAnimationHandler.post(new Runnable() {
#Override
public void run() {
// Update coordinates of the tray
mWindowParams.x = (2*(mWindowParams.x-mDestX))/3 + mDestX;
mWindowParams.y = (2*(mWindowParams.y-mDestY))/3 + mDestY;
mWindowManager.updateViewLayout(mRootLayout, mWindowParams);
// Cancel animation when the destination is reached
if (Math.abs(mWindowParams.x-mDestX)<2 && Math.abs(mWindowParams.y-mDestY)<2){
TrayAnimationTimerTask.this.cancel();
mTrayAnimationTimer.cancel();
}
}
});
}
}
}
Related
I have this android project, can not identify why it is eating up RAM ? Note there is no processing just RAM being filled in. I have read Android RAM issues and how to solve, but can't make out what to do. I am new to both android and java.
Noticed just now (in Android Monitor - RAM) my app is using only 4MB of memory.
If anyone tries to run (please do - MainActivity is launcher and MyCanvas is just a class used as View) this, i can use speed variable as high as 100 (even more maybe), make thread call back in 10ms or even more frequent - it creates no problem. But as soon as I touch and move garbage collector comes pauses everything.
MyCanvas.java (used as view)
package com.abc.mygraphics;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
import java.util.Random;
import android.os.Handler;
public class MyCanvas extends View {
public static Paint paint;
//public static int n = 5000;
public static int N = 100, particleSize = 3;
public static int height, width;
public static float[][] pos = new float[N][2];
public static float[][] pos0 = new float[N][2];
//public static float distX, distY, dist;
Handler handler = new Handler();
public static int speed = 1;
public static int gravityX, gravityY;
public static Random random = new Random();
public static int[] colorList = new int[10];
public static int sphereSize = 100, M = 10;
public static float[] distance = new float[N];
public static int[][] gravity = new int[N][2];
public static boolean[] direction = new boolean[N];
public static int[] moved = new int[N];
public MyCanvas(Context context) {
super(context);
width = MainActivity.sharedPreferences.getInt("screenX", 200);
height = MainActivity.sharedPreferences.getInt("screenY", 200);
colorList = new int[]{Color.RED, 0xffff4000, 0xffffff00, 0xff40ff00, 0xff00ff00, 0xff00ff80, 0xff0080ff, 0xff0000ff, 0xffbf00ff, 0xffff0040};
paint = new Paint();
paint.setColor(Color.GRAY);
int i;
for (i = 0; i < N; i++) {
pos[i][0] = random.nextInt(width);
pos[i][1] = random.nextInt(height);
pos0[i][0] = pos[i][0];
pos0[i][1] = pos[i][1];
moved[i] = 0;
direction[i] = true;
}
final Runnable r = new Runnable() {
public void run() {
invalidate();
handler.postDelayed(this, 100);
}
};
handler.postDelayed(r, 100);
}
public static void changeGravity(){
gravityX = MainActivity.sharedPreferences.getInt("x",200);
gravityY = MainActivity.sharedPreferences.getInt("y",200);
// gravityY -= 68;
for(int i=0;i<N;i++){
calcDist(i);
}
}
#Override
public void onDraw(Canvas canvas){
int i;
int x; //remove at some poitnt
canvas.drawColor(Color.BLACK);
//canvas.drawCircle(gravityX,gravityY, 50, paint);
for(i=0;i<N;i++) {
setPosition(i);
x = random.nextInt(10);
paint.setColor(colorList[x]);
canvas.drawCircle(pos[i][0], pos[i][1], particleSize, paint);
}
}
public static void setPosition(int i){
// this is wrong
if(moved[i] >= (int)distance[i]/speed){
direction[i] = !direction[i];
setGravity(i);
}
else{
pos[i][0] = pos0[i][0] + speed*moved[i]*(gravity[i][0]- pos0[i][0])/distance[i];
pos[i][1] = pos0[i][1] + speed*moved[i]*(gravity[i][1]- pos0[i][1])/distance[i];
moved[i]++;
}
}
public static void calcDist(int i){
setGravity(i);
distance[i] = (float) Math.sqrt( Math.pow((gravity[i][0]-pos[i][0]),2) + Math.pow((gravity[i][1]-pos[i][1]),2) );
}
public static void setGravity(int i){
// do not forget to set pos0 in both cases
if(direction[i]){
gravity[i][0] = gravityX;
gravity[i][1] = gravityY;
}
else{
// make this biased on radius of sphere
gravity[i][0] = random.nextInt(width);
gravity[i][1] = random.nextInt(height);
}
pos0[i][0] = pos[i][0];
pos0[i][1] = pos[i][1];
moved[i]=0;
}
}
Main Activity.java
package com.abc.mygraphics;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.TextView;
import com.abc.mygraphics.MyCanvas;
import org.w3c.dom.Text;
public class MainActivity extends AppCompatActivity {
//DrawingView dr = new DrawingView(this);
public static SharedPreferences sharedPreferences;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels;
sharedPreferences = getSharedPreferences( getPackageName() + "_preferences", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("screenX",width);
editor.putInt("screenY", height);
editor.putInt("x", 200);
editor.putInt("y", 200);
editor.commit();
setContentView(new MyCanvas(this));
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// int x = (int)event.getX();
//int y = (int)event.getY();
int x = (int) event.getRawX();
int y = (int) event.getRawY();
//sharedPreferences = getSharedPreferences("CheckSharing",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("x", x);
editor.putInt("y", y);
editor.apply();
MyCanvas.changeGravity();
return false;
}
}
Got my problem.
I was trying to call my methods every time a touch event happens, this is something we can't do because when you drag your mouse there are literally thousands(possibly more) touch events happening.
Try understanding from code. In main activity we have our onTouch event listener which calls changeGravity() method which in turn calls calcDist() and setGravity() (from calcDist() ) . So thats a lot of garbage being generated and hence the GC comes in to play, it pauses the application and everything seems like hanged.
Solution - Just place the calcDist() call inside thread, so whatever be the vakue of gravity will come in effect in 10ms. This is something our emulator and phone are capable of, compared to what happens if we call from changeGravity() method.
I have this slider which is an overlay view. It appears over the navigationbar when it below the screen.
normal
When a chrome browser is opened, it turns navigationbar to black and the rest works fine.
in browser
I want to achieve this effect permanetly for the navigationbar while the slider is running
The code overlay slider is here
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import com.sleepycoat.tapxicon.utils.ScreenUtils;
import java.security.InvalidAlgorithmParameterException;
import static android.view.MotionEvent.ACTION_OUTSIDE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
/**
* Created by egslava on 24/08/16.
* Unfortunately, Android system is not supported (or I could find how) managing keyboard in windows
* (not activities) that are always on top. So we need to manage keyboard manually.
*/
public class TopScreenDrawerLogic {
private static final String TAG = "TopScreenDrawerLogic";
final Keyboarder keyboarder;
// private final View fakeFocus;
View visibleView;
DrawerView drawer;
ScrollerLogic scroller;
private final ScreenUtils utils;
private final WindowManager wm;
public static final int COMMON_WINDOW_FLAGS =
FLAG_LAYOUT_NO_LIMITS | // for fast "resizing". Window can be moved out of screen
FLAG_NOT_TOUCH_MODAL | // other windows (on the background, that our window is not overlapped) can intercept touch events
FLAG_LAYOUT_IN_SCREEN; // need for right positioning (getting into account status bar)
// when FLAG_LAYOUT_IN_SCREEN is set getHeight() will return value - navigation bar height
public static final int BACKGROUND_WINDOW_FLAGS = COMMON_WINDOW_FLAGS |
FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM; // "back" and other hardware buttons will go throw window
public static final int FOREGROUND_WINDOW_FLAGS = COMMON_WINDOW_FLAGS |
// FLAG_LOCAL_FOCUS_MODE |
// FLAG_NOT_TOUCHABLE | // if we want go clicks throw the window
FLAG_WATCH_OUTSIDE_TOUCH; // need to know when user touched outside of window to "unfocus"
private final InputMethodManager imm;
public static WindowManager.LayoutParams createLayout() {
return new WindowManager.LayoutParams(
MATCH_PARENT, MATCH_PARENT, TYPE_PHONE, FOREGROUND_WINDOW_FLAGS, PixelFormat.TRANSLUCENT);
}
//////////////////////////////////////////////////////
// mrtndat add 9/9
//////////////////////////////////////////////////////
public static WindowManager.LayoutParams createLayout(Context context) {
// int w
Point navBarSize = ScreenUtils.getNavigationBarSize(context);
Point screenSize = ScreenUtils.getRealScreenSize(context);
int maxHeight = navBarSize != null ? (screenSize.y - navBarSize.y) :
screenSize.y;
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
// params.gravity = Gravity.TOP;
// params.x = 0;
// int diff = 0;
// if (navBarSize != null) {
// diff = maxHeight - navBarSize.y;
// }
// if (navBarSize != null) {
// params.y = -navBarSize.y+144;
// }
return params;
}
//////////////////////////////////////////////////////
// mrtndat end 9/9
//////////////////////////////////////////////////////
public TopScreenDrawerLogic(DrawerView drawer, View visibleView) {
this.visibleView = visibleView;
this.drawer = drawer;
scroller = new ScrollerLogic(drawer);
keyboarder = new Keyboarder(drawer);
utils = new ScreenUtils(drawer.getContext());
wm = drawer.windowManager;
imm = (InputMethodManager) drawer.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
// this.fakeFocus = fakeFocus;
}
public int minY() {
return 0;
}
public int maxY() {
int[] location = new int[2];
visibleView.getLocationInWindow(location);
int visibleViewTop = location[1];
ViewGroup.MarginLayoutParams margins = (ViewGroup.MarginLayoutParams) visibleView.getLayoutParams();
int visibleViewBottom = visibleViewTop + visibleView.getHeight() + margins.bottomMargin; //just a bit margin;
return utils.getDisplayHeight() - visibleViewBottom;// - navBarHeight;
}
private int minY(int value) {
return Math.max(value, minY());
}
private int maxY(int value) {
return Math.min(maxY(), value);
}
;
public int boundY(int y) {
return maxY(minY(y));
}
// difference between nearest correct Y value and given
public int yCorrection(int y) {
return y - boundY(y);
}
public int shiftDrawer(int dy) {
return shiftDrawer(dy, false);
}
/**
* shifts drawer and returns new y coordinate
*/
public int shiftDrawer(int dy, boolean animated) {
WindowManager.LayoutParams params = drawer.getLayoutParams();
WindowManager wm = drawer.windowManager;
// params.y = params.y + dy;
if (dy > 1500) {
new Throwable().printStackTrace();
}
final int newY = drawer.logic.boundY(params.y + dy);
if (animated) {
new TranslateDrawerAnim(drawer, boundY(drawer.getLayoutParams().y + (int) dy)/* target layout height */, 250).execute();
} else {
params.y = newY;
wm.updateViewLayout(drawer, params);
}
return params.y;
}
public int shiftDrawerByScreenPercent(float dy, boolean animated) {
return shiftDrawer((int) (utils.getDisplayHeight() / 100.0f * dy), animated);
}
public static final int STATE_UNDEFINED = 0;
public static final int STATE_FOREGROUND = 1;
public static final int STATE_BACKGROUND = 2;
public static final int INITIAL_STATE = STATE_FOREGROUND;
public int state = INITIAL_STATE;
public void resetState(View focusedView) {
if (INITIAL_STATE == STATE_BACKGROUND) {
makeBackground();
} else if (INITIAL_STATE == STATE_FOREGROUND) {
makeForeground();
} else throw new RuntimeException(new InvalidAlgorithmParameterException("Strange state"));
}
public void makeBackground() {
new Throwable().printStackTrace();
Log.d(TAG, "makeBackground()" + ", previous state = " + stateToString(state));
if (state == STATE_BACKGROUND) return;
state = STATE_BACKGROUND;
imm.hideSoftInputFromWindow(drawer.getWindowToken(), 0);
WindowManager.LayoutParams params = drawer.getLayoutParams();
WindowManager wm = drawer.windowManager;
params.softInputMode = SOFT_INPUT_STATE_ALWAYS_HIDDEN;
params.flags = BACKGROUND_WINDOW_FLAGS;
wm.updateViewLayout(drawer, params);
// final View focus = drawer.findFocus();
// if (focus != null) focus.postDelayed(new Runnable() {
// #Override
// public void run() {
// imm.hideSoftInputFromWindow(drawer.getWindowToken(), 0, new ResultReceiver(new Handler(new Handler.Callback() {
// #Override
// public boolean handleMessage(Message message) {
// fakeFocus.requestFocus();
// keyboarder.applyPos();
// return true;
// }
// })));
// }
// }, 250);
}
public String stateToString(int state) {
switch (state) {
case STATE_BACKGROUND:
return "background";
case STATE_FOREGROUND:
return "foreground";
default:
throw new RuntimeException("Invalid state");
}
}
public void makeForeground() {
new Throwable().printStackTrace();
Log.d(TAG, "makeForeground()" + ", previous state = " + stateToString(state));
if (state == STATE_FOREGROUND) return;
state = STATE_FOREGROUND;
WindowManager.LayoutParams params = drawer.getLayoutParams();
WindowManager wm = drawer.windowManager;
params.flags = FOREGROUND_WINDOW_FLAGS;
// params.softInputMode = SOFT_INPUT_STATE_UNCHANGED;
params.softInputMode = SOFT_INPUT_STATE_HIDDEN;
// params.softInputMode = SOFT_INPUT_STATE_VISIBLE;
wm.updateViewLayout(drawer, params);
// request focus on focused element. Why? The reason:
// 1. when window is in background state it can't be focused.
// 2. when window is in foreground state some time it focuses last focused element
// 3. when this happens Android shows keyboard but DOESN'T call onFocusChanged
// 4. #Keyboarder class can't process this case correctly and move drawer on keyboard level
// final View focus = drawer.findFocus();
// if (focus != null)focus.postDelayed(new Runnable() {
// #Override
// public void run() {
// focus.requestFocus();
// }
// }, 250);
}
public void dispatchTouchEvent(MotionEvent e) {
Log.d(TAG, "dispatchTouchEvent() called with: " + "e = [" + e + "]");
switch (e.getAction()) {
case ACTION_OUTSIDE:
makeBackground();
break;
default:
makeForeground();
break;
}
}
public boolean delegateOnTouch(MotionEvent e) {
Log.d(TAG, "delegateOnTouch() called with: " + "e = [" + e + "]");
keyboarder.delegateOnTouch(e);
return scroller.delegateOnTouch(e);
}
// need to process keyboard by ourselves
public void delegateOnInputClick(final View v) {
keyboarder.delegateOnInputClick(v);
}
public void delegateOnInputFocus(final View v, final boolean b) {
keyboarder.delegateOnInputFocus(v, b);
}
public boolean delegateOnInterceptTouch(MotionEvent e) {
return scroller.delegateOnInterceptTouch(e);
}
public void callWhenEnterIsPressed() {
}
public void callWhenKeypressed() { // for backpressing
}
public void callWhenKeyboardIsShown() {
}
public void delegateOnKeyPreIme(int keyCode, KeyEvent event) {
keyboarder.delegateOnKeyPreIme(keyCode, event);
}
}
I want to achieve this affect of chrome browser by using Transparent activity with the overlay layout but again the slider appear over the the transparent activity.
I wish to create a floating button which will hover over the entire Android screen. When the button or hovering icon is clicked, it should open a small popupwindow.
I was able to create the hovering icon using service class however I am unable to launch popupwindow. Whenever I click the floating icon, the error log says:
Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.ImageView;
import android.widget.PopupWindow;
/**
* Created by sejal on 17-Oct-15.
*/
public class bubble extends Service{
PopupWindow popw;
private WindowManager windowManager;
private ImageView floatingFaceBubble;
public void onCreate() {
super.onCreate();
floatingFaceBubble = new ImageView(this);
//a face floating bubble as imageView
floatingFaceBubble.setImageResource(R.drawable.bubble);
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
//here is all the science of params
final LayoutParams myParams = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
LayoutParams.TYPE_PHONE,
LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
myParams.gravity = Gravity.TOP | Gravity.LEFT;
myParams.x=0;
// add a floatingfacebubble icon in window
windowManager.addView(floatingFaceBubble, myParams);
try{
floatingFaceBubble.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getpopuppwindow();
}
});
//for moving the picture on touch and slide
floatingFaceBubble.setOnTouchListener(new View.OnTouchListener() {
LayoutParams paramsT = myParams;
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
private long touchStartTime = 0;
#Override
public boolean onTouch(View v, MotionEvent event) {
//remove face bubble on long press
/* if(System.currentTimeMillis()-touchStartTime> ViewConfiguration.getLongPressTimeout() && initialTouchX== event.getX()){
//// windowManager.removeView(floatingFaceBubble);
//// stopSelf();
// return false;
// } */
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
touchStartTime = System.currentTimeMillis();
initialX = myParams.x;
initialY = myParams.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_MOVE:
myParams.x = initialX + (int) (event.getRawX() - initialTouchX);
myParams.y = initialY + (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(v, myParams);
break;
}
return false;
}
});
} catch (Exception e){
e.printStackTrace();
}
}
//(ViewGroup) floatingFaceBubble.findViewById(R.id.pop)
private void getpopuppwindow() {
try {
System.out.print("111111");
LayoutInflater inflater = (LayoutInflater)bubble.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
System.out.print("222222");
View layout = inflater.inflate(R.layout.popup,(ViewGroup) floatingFaceBubble.findViewById(R.id.pop));
System.out.print("333333");
popw = new PopupWindow(layout ,300,100 ,true) ;
System.out.print("444444");
popw.showAtLocation(layout, Gravity.CENTER,0,0);
}
catch(Exception e)
{
e.printStackTrace();
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
You should not do these ui operations in your service class. Because after you show your button service instance will be removed and there is no context when you click the button. I think you should follow similar approach like below.
Service Class:
Intent activityIntent = new Intent(context, MainActivity);
activityIntent.putExtra("showPopup", true);
context.startActivity(activityIntent);
Activity Class:
onCreate(){
boolean showPopUp = getIntent().getBooleanExtra("showPopup", false);
if(showPopUp){
// Show your popup here
}
}
I'm learning Android programming.
So I managed to implement a simple app that rolls a ball over the screen if you tilt yout phone. But right now it is as simple as:
if roll > 0 then xpos++ else xpos-- end and the same for ypos.
So I want to calculate a more exact direction and also I would like the ball to roll faster the more the phone is tilting.
So if I know the tilt in the roll direction and the pitch direction, how do I calculate the direction and speed of the ball?
Here is how:
package benyamephrem.tiltball;
import android.graphics.Point;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Handler;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.SensorEventListener;
import android.widget.Toast;
public class TiltBall extends ActionBarActivity {
BallView mBallView = null;
Handler RedrawHandler = new Handler(); //so redraw occurs in main thread
Timer mTmr = null;
TimerTask mTsk = null;
int mScrWidth, mScrHeight;
android.graphics.PointF mBallPos, mBallSpd;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE); //hide title bar
//set app to full screen and keep screen on
getWindow().setFlags(0xFFFFFFFF, LayoutParams.FLAG_FULLSCREEN | LayoutParams.FLAG_KEEP_SCREEN_ON);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tilt_ball);
//create pointer to main screen
final FrameLayout mainView = (android.widget.FrameLayout) findViewById(R.id.main_view);
//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 / 5;
mBallSpd.x = 0;
mBallSpd.y = 0;
//create initial ball
mBallView = new BallView(this, mBallPos.x, mBallPos.y, 75);
mainView.addView(mBallView); //add ball to main screen
mBallView.invalidate(); //call onDraw in BallView
//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)
//***Change speed here by multiplying event values by bigger numbers***
mBallSpd.x = -event.values[0] * (30/10);
mBallSpd.y = event.values[1] * (30/10);
//timer event will redraw ball
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
} //ignore
},
((SensorManager) getSystemService(Context.SENSOR_SERVICE))
.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0),
SensorManager.SENSOR_DELAY_NORMAL);
//listener for touch event
mainView.setOnTouchListener(new android.view.View.OnTouchListener() {
public boolean onTouch(android.view.View v, android.view.MotionEvent e) {
//set ball position based on screen touch
mBallPos.x = e.getX();
mBallPos.y = e.getY();
//timer event will redraw ball
return true;
}
});
} //OnCreate
//listener for menu button on phone
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add("Exit"); //only one menu item
return super.onCreateOptionsMenu(menu);
}
//listener for menu item clicked
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
if (item.getTitle() == "Exit") //user clicked Exit
finish(); //will call onPause
return super.onOptionsItemSelected(item);
}
//For state flow see http://developer.android.com/reference/android/app/Activity.html
#Override
public void onPause() //app moved to background, stop background threads
{
mTmr.cancel(); //kill\release timer (our only background thread)
mTmr = null;
mTsk = null;
super.onPause();
}
#Override
public void onResume() //app moved to foreground (also occurs at app startup)
{
//create timer to move ball to new position
mTmr = new Timer();
mTsk = new TimerTask() {
public void run() {
//if debugging with external device,
// a log cat viewer will be needed on the device
Log.d("TiltBall", "Timer Hit - " + mBallPos.x + ":" + mBallPos.y);
//move ball based on current speed
mBallPos.x += mBallSpd.x;
mBallPos.y += mBallSpd.y;
//if ball goes off screen, reposition to opposite side of screen
if (mBallPos.x > mScrWidth) mBallPos.x = 0;
if (mBallPos.y > mScrHeight) mBallPos.y = 0;
if (mBallPos.x < 0) mBallPos.x = mScrWidth;
if (mBallPos.y < 0) mBallPos.y = mScrHeight;
//update ball class instance
mBallView.x = mBallPos.x;
mBallView.y = mBallPos.y;
//redraw ball. Must run in background thread to prevent thread lock.
RedrawHandler.post(new Runnable() {
public void run() {
mBallView.invalidate();
}
});
}
}; // TimerTask
mTmr.schedule(mTsk, 10, 10); //start timer
super.onResume();
} // onResume
#Override
public void onDestroy() //main thread stopped
{
super.onDestroy();
//wait for threads to exit before clearing app
System.runFinalizersOnExit(true);
//remove app from memory
android.os.Process.killProcess(android.os.Process.myPid());
}
//listener for config change.
//This is called when user tilts phone enough to trigger landscape view
// we want our app to stay in portrait view, so bypass event
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
}
} //TiltBallActivity
Here is the BallView class;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
public class BallView extends View {
public float x;
public float y;
private final int r;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//construct new ball object
public BallView(Context context, float x, float y, int r) {
super(context);
//color hex is [transparncy][red][green][blue]
mPaint.setColor(0xFF1325E0); //not transparent. color is blue
this.x = x;
this.y = y;
this.r = r; //radius
}
//qcalled by invalidate()
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, r, mPaint);
}
public int getRadius(){
return r;
}
}
This is not my code but I forgot its source so credits to whoever made it. I am using it for a current project I'm working on.
I have a little problem with my Window dimming.
Basically, I want to set the dimAmount of my Activity to zero as soon as I swipe it into one direction.
Please be aware that my Activity is displayed as a dialog, and can be swiped to the left or right. This works perfectly fine. But the setWindowDim() method has no effect when called after swipe.
If i call the setWindowDim inside my onCreate method, it works perfectly fine.
I have no idea why it doesnt work anywhere else.
public class FinishDialog extends Activity {
private FrameLayout frame = null;
private GestureDetector gd = null;
private int displaywidth = 0;
private int original_x = 0;
private int dialog_width = 0;
private final int POS_LEFT = -1;
private final int POS_MID = 0;
private final int POS_RIGHT = 1;
/** the dialogs current position, POS_MID on startup */
private int current_pos = POS_MID;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
frame = new FrameLayout(this);
gd = new GestureDetector(this, new TouchManager(this));
// fill the challenge layout into the framelayout
frame.addView(LayoutInflater.from(getBaseContext()).inflate(R.layout.finishdialog, null));
setContentView(frame);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) frame.getLayoutParams();
GameLogic g = new GameLogic();
displaywidth = g.getDisplayWidth(this);
lp.width = displaywidth - displaywidth / 6;
lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
LinearLayout llFinish = (LinearLayout) findViewById(R.id.llFinishDialog);
LinearLayout.LayoutParams lpLL = (LinearLayout.LayoutParams) llFinish.getLayoutParams();
lp.height = lpLL.height;
frame.setLayoutParams(lp);
// setWindowDim(0.0f); ---> if i set the dim here, it works perfectly fine
original_x = (int) frame.getX();
dialog_width = lp.width;
}
private void setWindowDim(float dim) {
Log.i("FinishDialog", "Setting window dim to " + dim + ".");
WindowManager.LayoutParams lpWin = getWindow().getAttributes();
lpWin.dimAmount = dim;
getWindow().setAttributes(lpWin);
}
/**
* move the dialog, depending on the swipe direction and the
* current position of the dialog
* #param action
*/
public void interpretTouch(int action) {
switch(action) {
case TouchManager.MOVE_DIALOG_RIGHT:
if(frame != null) {
if(current_pos == POS_MID) {
swipeDialog(600, frame, 0, dialog_width, 0, 0);
current_pos = POS_RIGHT;
setWindowDim(0.0f); // here setting the dim has no effect
} else if (current_pos == POS_LEFT) {
swipeDialog(600, frame, - dialog_width, original_x, 0, 0);
current_pos = POS_MID;
setWindowDim(0.9f); // here setting the dim has no effect
} else if (current_pos == POS_RIGHT) {
// if we are on the right and swipe right, nothing happens
}
}
Log.i("Challenge", "Moving dialog to the right.");
break;
case TouchManager.MOVE_DIALOG_LEFT:
if(frame != null) {
if(current_pos == POS_MID) {
swipeDialog(600, frame, 0, -dialog_width, 0, 0);
current_pos = POS_LEFT;
setWindowDim(0.0f); // here setting the dim has no effect
} else if (current_pos == POS_LEFT) {
// if we are on the left and swipe left, nothing happens
} else if (current_pos == POS_RIGHT) {
swipeDialog(600, frame, dialog_width, original_x, 0, 0);
current_pos = POS_MID;
setWindowDim(0.9f); // here setting the dim has no effect
}
}
Log.i("Challenge", "Moving dialog to the left.");
break;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return gd.onTouchEvent(event);
}
private void swipeDialog(int time, View framelayout, int fromDeltaX, int toDeltaX, int fromDeltaY, int toDeltaY) {
Log.i("FinishDialog", "Dialog swiped.");
TranslateAnimation trans = new TranslateAnimation(fromDeltaX, toDeltaX,
fromDeltaY, toDeltaY);
trans.setFillAfter(true);
trans.setFillEnabled(true);
trans.setDuration(time);
framelayout.startAnimation(trans);
}
}
Starting this activity right after I change the Window dim finally did the job.
Unfortunately, now the Screen flashes pretty "ugly" when the RefreshActivity gets started, does anyone have a solution for that?
import android.app.Activity;
import android.os.Bundle;
public class RefreshActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
finish();
}
}