Intereting Posts
Android 1.6 ksoap2 "RuntimeException: не может сериализоваться: java.util.GregorianCalendar ..", передавая параметр datetime Java.lang.IndexOutOfBoundsException: Недопустимый индекс 13, размер 13 Этот класс должен быть общедоступным (android.support.v7.internal.widget.ActionBarView.HomeView) Как читать / писать логическое значение при реализации интерфейса Parcelable? Android: передать параметр службе из Activity Как настроить VPN программно? Как показать счетчик FPS в окне установки Chrome на (Android)? Невозможно изменить целевой API в AVD Manager Предупреждение о безопасности в libpng в моей консоли Google Play Когда тип ввода = число и браузеры браузера отображают поле ввода меньше Справочные ресурсы в javadoc Можно ли получить конкретные сведения об ошибке из Android SQLiteConstraintException? Firebase продолжает бросать идентификатор клиента OAuth2 в конфигурации сервера не найден Запуск Node.Js на Android Настройка пользовательской темы в настройках списка Android

Плавающий вид на экране Android

Я пытался сделать плавающий вид, который пользователь может перетащить на экран.

Идея состоит в том, чтобы запустить службу, а затем раздуть представление на экране.

Но есть проблема, вместо того чтобы принимать событие принадлежит самому себе, оно принимает все события ввода пользователя.

Вот мой код: 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> 

Плавающий вид, который можно перетащить:

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

И услуга:

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

Полный проект: https://github.com/shanwu/shanwu_coding_base/tree/xxx/floatAndroidPractice

Я пробовал рисовать изображение на холсте, но это никуда не денется. У меня есть два примера: сначала EatHeat на github, откуда я учился, а второй – мой (github), где у меня есть пример холста, который не является осязаемым, и несколько других виджетов. Возможно, это может заставить вас двигаться в правильном направлении, может быть, нет, но это работает

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)); } }); } } 

По умолчанию View будет занимать всю доступную площадь, если ее выложить с помощью WRAP_CONTENT. Вам нужно явно указать размер представления в вашем WindowManager.LayoutParams, переопределить View.onMeasure или (в идеале) расширить ImageView, а не View.