差补器原理:
图标拖拽:
activity_drag_view.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 2个TextView,一个显示一个隐藏 --> <TextView android:id="@+id/tv_top" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:background="@drawable/call_locate_blue" android:gravity="center" android:padding="15dp" android:text="按住提示框拖到任意位置\n按手机返回键立即生效" android:textColor="@color/black" android:textSize="18sp" /> <TextView android:id="@+id/tv_bottom" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:background="@drawable/call_locate_blue" android:gravity="center" android:padding="10dp" android:text="按住提示框拖到任意位置\n按手机返回键立即生效" android:textColor="@color/black" android:textSize="18sp" android:visibility="invisible" /> <!-- 拖拽的图片 --> <ImageView android:id="@+id/iv_drag" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="90dp" android:src="@drawable/drag" /> </RelativeLayout>
package com.itheima52.mobilesafe.activity; import android.app.Activity; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.os.SystemClock; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.itheima52.mobilesafe.R; /** * 修改归属地显示位置 * * 半透明效果:清单文件<activity android:name=".activity.DragViewActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> 这个acticity透明没有标题栏。 xml文件<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#5000" 背景半透明 > */ public class DragViewActivity extends Activity { private TextView tvTop; private TextView tvBottom; private ImageView ivDrag; private int startX; private int startY; private SharedPreferences mPref; long[] mHits = new long[2];// 数组长度表示要点击的次数 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_drag_view); mPref = getSharedPreferences("config", MODE_PRIVATE); tvTop = (TextView) findViewById(R.id.tv_top); tvBottom = (TextView) findViewById(R.id.tv_bottom); ivDrag = (ImageView) findViewById(R.id.iv_drag); int lastX = mPref.getInt("lastX", 0); int lastY = mPref.getInt("lastY", 0); // 获取屏幕宽高 final int winWidth = getWindowManager().getDefaultDisplay().getWidth(); final int winHeight = getWindowManager().getDefaultDisplay().getHeight(); if (lastY > winHeight / 2) {// 上边显示,下边隐藏 tvTop.setVisibility(View.VISIBLE); tvBottom.setVisibility(View.INVISIBLE); } else { tvTop.setVisibility(View.INVISIBLE); tvBottom.setVisibility(View.VISIBLE); } // ivDrag.getWidth();获取不到,因为还没有绘制完毕。 // onMeasure(测量view), onLayout(安放位置), onDraw(绘制) // ivDrag.layout(lastX, lastY, lastX + ivDrag.getWidth(),lastY + ivDrag.getHeight());//不能用这个方法,因为还没有测量完成,就不能安放位置,下面的方法就可以,RelativeLayout是控件的父控件。 RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) ivDrag.getLayoutParams();// 获取布局对象 layoutParams.leftMargin = lastX;// 设置左边距 layoutParams.topMargin = lastY;// 设置top边距 ivDrag.setLayoutParams(layoutParams);// 重新设置位置 ivDrag.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1); mHits[mHits.length - 1] = SystemClock.uptimeMillis();// 开机后开始计算的时间 if (mHits[0] >= (SystemClock.uptimeMillis() - 500)) { // 把图片居中 ivDrag.layout(winWidth / 2 - ivDrag.getWidth() / 2, ivDrag.getTop(), winWidth / 2 + ivDrag.getWidth() / 2, ivDrag.getBottom()); } } }); // 设置触摸监听 ivDrag.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 初始化起点坐标 startX = (int) event.getRawX(); startY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: int endX = (int) event.getRawX(); int endY = (int) event.getRawY(); // 计算移动偏移量 int dx = endX - startX; int dy = endY - startY; // 更新左上右下距离 int l = ivDrag.getLeft() + dx; int r = ivDrag.getRight() + dx; int t = ivDrag.getTop() + dy; int b = ivDrag.getBottom() + dy; // 判断是否超出屏幕边界, 注意状态栏的高度 if (l < 0 || r > winWidth || t < 0 || b > winHeight - 20) { break; } // 根据图片位置,决定提示框显示和隐藏 if (t > winHeight / 2) {// 上边显示,下边隐藏 tvTop.setVisibility(View.VISIBLE); tvBottom.setVisibility(View.INVISIBLE); } else { tvTop.setVisibility(View.INVISIBLE); tvBottom.setVisibility(View.VISIBLE); } // 更新界面(左上右下),因为已经绘制完成了,所以可以使用layout()方法。 ivDrag.layout(l, t, r, b); // 重新初始化起点坐标 startX = (int) event.getRawX(); startY = (int) event.getRawY(); break; case MotionEvent.ACTION_UP: // 记录坐标点 Editor edit = mPref.edit(); edit.putInt("lastX", ivDrag.getLeft()); edit.putInt("lastY", ivDrag.getTop()); edit.commit(); break; default: break; } return false;//事件要向下传递,让onclick(双击事件)可以响应 } }); } }
/** * 自定义归属地浮窗Toast, 需要权限android.permission.SYSTEM_ALERT_WINDOW */ private void showToast(String text) { mWM = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE); // 获取屏幕宽高 winWidth = mWM.getDefaultDisplay().getWidth(); winHeight = mWM.getDefaultDisplay().getHeight(); params = new WindowManager.LayoutParams(); params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; params.format = PixelFormat.TRANSLUCENT; params.type = WindowManager.LayoutParams.TYPE_PHONE;// 电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。 params.gravity = Gravity.LEFT + Gravity.TOP;// 将重心位置设置为左上方, // 也就是(0,0)从左上方开始,而不是默认的重心位置 params.setTitle("Toast"); int lastX = mPref.getInt("lastX", 0); int lastY = mPref.getInt("lastY", 0); // 设置浮窗的位置, 基于左上方的偏移量 params.x = lastX; params.y = lastY; // view = new TextView(this); view = View.inflate(this, R.layout.toast_address, null); int[] bgs = new int[] { R.drawable.call_locate_white, R.drawable.call_locate_orange, R.drawable.call_locate_blue, R.drawable.call_locate_gray, R.drawable.call_locate_green }; int style = mPref.getInt("address_style", 0); view.setBackgroundResource(bgs[style]);// 根据存储的样式更新背景 TextView tvText = (TextView) view.findViewById(R.id.tv_number); tvText.setText(text); mWM.addView(view, params);// 将view添加在屏幕上(Window) view.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 初始化起点坐标 startX = (int) event.getRawX(); startY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: int endX = (int) event.getRawX(); int endY = (int) event.getRawY(); // 计算移动偏移量 int dx = endX - startX; int dy = endY - startY; // 更新浮窗位置,WindowManager里面只可以用params实现位置的移动 params.x += dx; params.y += dy; // 防止坐标偏离屏幕 if (params.x < 0) { params.x = 0; } if (params.y < 0) { params.y = 0; } // 防止坐标偏离屏幕 if (params.x > winWidth - view.getWidth()) { params.x = winWidth - view.getWidth(); } if (params.y > winHeight - view.getHeight()) { params.y = winHeight - view.getHeight(); } // System.out.println("x:" + params.x + ";y:" + params.y); mWM.updateViewLayout(view, params); // 重新初始化起点坐标 startX = (int) event.getRawX(); startY = (int) event.getRawY(); break; case MotionEvent.ACTION_UP: // 记录坐标点 Editor edit = mPref.edit(); edit.putInt("lastX", params.x); edit.putInt("lastY", params.y); edit.commit(); break; default: break; } return true; } }); }
本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/p/5122992.html,如需转载请自行联系原作者