Android Floating View

I tried to make a floating view that the user can drag onto the screen.

The idea is to start the service and then inflate the presentation on the screen.

But the problem, instead of accepting the event belongs to itself, accepts the entire user input event.

here is my code: 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> 

floating view that can be dragged:

 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 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

+6
source share
2 answers

I tried your way of drawing an image on canvas, but it will not go anywhere. Example, EatHeat github , how I found out. Maybe it can make you move 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)); } }); } } 
+12
source

By default, View will occupy the entire available volume if it is laid out using WRAP_CONTENT. You need to explicitly specify the size of the view in WindowManager.LayoutParams, override View.onMeasure, or (ideally) extend ImageView, not View.

0
source

Source: https://habr.com/ru/post/972215/


All Articles