Floating view on Android screen

android, android-custom-view, floating, view

Solution

I tried your way of drawing the image on a canvas, but that didn't go anywhere. An example, EatHeat's github, where I learned from. Maybe this can get you rolling in the right direction, maybe not, but it worked for me.

WalkingIconService.java

package ...
//imports

public class WalkingIconService extends Service {
    private WindowManager mWindowManager;
    private ImageView image;

    public void onCreate() {
        super.onCreate();
        image = new ImageView(this);

        image.setImageResource(R.drawable.ic_launcher);

        mWindowManager = (WindowManager)getSystemService(WINDOW_SERVICE);

        final LayoutParams paramsF = new WindowManager.LayoutParams(
            LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT,
            LayoutParams.TYPE_PHONE,
            LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);

        paramsF.gravity = Gravity.TOP | Gravity.LEFT;
        paramsF.x=0;
        paramsF.y=100;
        mWindowManager.addView(image, paramsF);

        try{

            image.setOnTouchListener(new View.OnTouchListener() {
                WindowManager.LayoutParams paramsT = paramsF;
                private int initialX;
                private int initialY;
                private float initialTouchX;
                private float initialTouchY;
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch(event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        initialX = paramsF.x;
                        initialY = paramsF.y;
                        initialTouchX = event.getRawX();
                        initialTouchY = event.getRawY();
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                    case MotionEvent.ACTION_MOVE:
                        paramsF.x = initialX + (int) (event.getRawX() - initialTouchX);
                        paramsF.y = initialY + (int) (event.getRawY() - initialTouchY);
                        mWindowManager.updateViewLayout(v, paramsF);
                        break;
                    }
                    return false;
                }
            });
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    @Overrride
    public void onDestroy(){
        super.onDestory();
    }

}

MainActivity.java

package ...
//imports

public class MainActivity extends Activity {

    @Override
    public void onCreate(icicle) {
        super.onCreate(icicle);
        setcontentView(R.layout.activity_main);
        Button b = (Button)findViewById(R.id.tv);
        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //toast
                startService(new Intent(MainActivity.this, WalkingIconService.class));
            }
        });
        //stopService (from my original code)
        Button stop = (Button)findViewById.(R.id.btnStop);
        stop.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(new Intent(MainActivity.this, WalkingIconService.class));
            }
        });
    }
}

Problem

I was trying to make a floating view which user can drag around on the screen. The idea is to launch a service and then inflate a view on the screen. But there's a problem, instead of taking the event belongs to itself, it takes all the user input event. here's my code: the manifest.xml: ``` <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.floatandroidpractice" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.floatandroidpractice.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="com.example.floatandroidpractice.WalkingIconService" /> </application> </manifest> ``` the floating view which can be drag around: ``` package com.example.floatandroidpractice; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.view.MotionEvent; import android.view.View; public class littleIconView extends View { private float viewX; private float viewY; private Paint mPaint; private Bitmap androidIcon; public littleIconView(Context context) { super(context); mPaint = new Paint(); mPaint.setColor(Color.BLACK); androidIcon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); } @Override public void onDraw(Canvas cvs) { cvs.drawBitmap(androidIcon, viewX - androidIcon.getWidth() / 2, viewY - androidIcon.getHeight() / 2, mPaint); } @Override public boolean onTouchEvent(MotionEvent event) { boolean touchedX = Math.abs(viewX - event.getX()) > androidIcon.getWidth(); boolean touchedY = Math.abs(viewY - event.getY()) > androidIcon.getHeight(); boolean isValidTouch = !touchedX && !touchedY; if (isValidTouch) { if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE || event.getAction() == MotionEvent.ACTION_UP) { viewX = event.getX(); viewY = event.getY(); } invalidate(); return true; } else return false; } } ``` and the service: ``` package com.example.floatandroidpractice; import android.app.Service; import android.content.Intent; import android.graphics.PixelFormat; import android.os.IBinder; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; public class WalkingIconService extends Service { @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { littleIconView a = new littleIconView(getApplicationContext()); LayoutParams mLayoutParams = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0, PixelFormat.TRANSPARENT); WindowManager mWindowManager = (WindowManager) this.getSystemService(WINDOW_SERVICE); mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_LAYOUT_INSET_DECOR | LayoutParams.FLAG_LAYOUT_IN_SCREEN; mWindowManager.addView(a, mLayoutParams); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; } } ``` full project: https://github.com/shanwu/shanwu_coding_base/tree/xxx/floatAndroidPractice

Original source