[mobilesafe] 01_更改归属地提示框显示的位置

Android 4.0

更改归属地提示框显示的位置

view对象渲染的两个阶段:1、测量参数——布局参数生效
LayoutParams params = (LayoutParams) iv_dragview.getLayoutParams();
params.leftMargin = left;
params.topMargin = top;
// 重新设置回去
iv_dragview.setLayoutParams(params);  
2、渲染之后,layout()生效
3、在onCreate()中不能用 int tv_height = tv_dragview.getHeight();来设置view对象的位置,因为此时view对象还没有初始化出来,还没有调用onMeasure(),view对象的宽度和高度都还没有确定,此时调用layout()方法,view对象在界面上显示不出来,
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }
此时,应该用
LayoutParams 来设置组件的位置。 
final LayoutParams iv_params = (LayoutParams) iv_dragview.getLayoutParams();
iv_params.leftMargin = left;
iv_params.topMargin = top;
注意:
在onCreate()方法中,调用iv_dragview.getHeight()等方法为0,因为view还没渲染,返回为0,layout()也不生效。
一、textview可以根据imageview的位置调整:imageview在上面textview在下面,imageview在下面textview在上面:
DragViewActivity.java 
if (top < (window_height / 2 - iv_dragview.getHeight() / 2)) {
// 当前iv_dragview的最上边top在窗体的上半部分,tv_dragview到底部
    tv_dragview.layout(tv_dragview.getLeft(), window_height-tv_height-40, tv_dragview.getRight(), window_height-40);
else if (bottom > (window_height / 2 + iv_dragview.getHeight() / 2)) {
// 当前iv_dragview的最下边bottom在窗体的下半部分,tv_dragview到顶部
    tv_dragview.layout(tv_dragview.getLeft(), 0, tv_dragview.getRight(), tv_height);
}
二、拨打电话时,位置为设置的位置:
ShowAddressService.java 
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        // 设置拨打电话提示框显示的位置,根据之前设置的位置来显示
        params.gravity = Gravity.LEFT + Gravity.TOP;// 默认是Gravity.CENTER
        params.x = sp.getInt("left", 0);// 要和上面的Gravity.LEFT等一起使用,否则,会被忽略掉
        params.y = sp.getInt("top", 0);
注意:如果没有配置
Gravity.LEFT 等,那么param.x就无效 

X position for this window. With the default gravity it is ignored. When using Gravity.LEFT or Gravity.START or Gravity.RIGHT or Gravity.END it provides an offset from the given edge.

三、保证imageview在上面时textview在下面imageview在下面时textview在上面,退出时保存,下次进来还是那样:
// 9、如果iv_dragview在上方,将tv_dragview放到下方
final int window_height = wm.getDefaultDisplay().getHeight();// 获取窗体高度
final int window_width = wm.getDefaultDisplay().getWidth();
int tv_height = sp.getInt("tv_height", 0);// FIXME bug
int tv_left = sp.getInt("tv_left", 0);
// /int tv_right = sp.getInt("tv_right", 0);
if (tv_height != 0) {
    Log.i(TAG"iv在上方,tv跑下去");
    if (top < (window_height / 2 - tv_height / 2)) { // iv_dragview.getHeight()
        LayoutParams tv_params = (LayoutParams) tv_dragview.getLayoutParams();
        tv_params.topMargin = window_height-tv_height-40;
        // tv_params.bottomMargin = window_height-40;//这个不要,否则显示不正确
        tv_params.leftMargin = tv_left;
        // tv_params.rightMargin = tv_right;//这个不要,否则显示不正确
    }
}  
结果:

核心代码:
package cn.zengfansheng.mobilesafe;
 
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
 
/**
* 13、拖动改变位置的Activity-Toast显示位置改变
* @author hacket
*/

public class DragViewActivity extends Activity {
 
    private static final String TAG = "DragViewActivity";
 
    private ImageView iv_dragview;// 更改toast显示位置的ImageView
    private SharedPreferences sp;//
 
    private WindowManager wm;//
 
    private TextView tv_dragview;// 更改toast显示位置的提示TextView
 
    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dragview);
 
        iv_dragview = (ImageView) this.findViewById(R.id.iv_dragview);
        sp = this.getSharedPreferences("config", MODE_PRIVATE);
        wm = (WindowManager) this.getSystemService(WINDOW_SERVICE);
        tv_dragview = (TextView) this.findViewById(R.id.tv_dragview);
 
        // 4、下次重新设置的时候,保存记录位置
        int left = sp.getInt("left", 0);
        int top = sp.getInt("top", 0);
        Log.i(TAG, "读取到距离左边:" + left);
        Log.i(TAG, "读取到距离顶部:" + top);
 
        // 注意:在onCreate()方法中,view对象的宽和高还没有计算出来,值为0,这种方式不行,获取不到组件宽和高度。
        // 5、设置iv_dragview的位置为上次保存的位置
//        int height = iv_dragview.getBottom() - iv_dragview.getTop();// iv_dragview高度
//        int width = iv_dragview.getRight() - iv_dragview.getLeft();// iv_dragview宽度
//        Log.i(TAG, "iv_dragview空间高度:" + height);
//        Log.i(TAG, "iv_dragview控件宽度:" + width);
//        // layout()是布局机制的第二个阶段,第一个阶段还是测量,只有测量后该方法才会生效
//        iv_dragview.layout(left, top, left + width, top + height);
 
        // 6、利用参数获取
        final LayoutParams iv_params = (LayoutParams) iv_dragview.getLayoutParams();
        iv_params.leftMargin = left;
        iv_params.topMargin = top;
 
        // 9、如果iv_dragview在上方,将tv_dragview放到下方
        final int window_height = wm.getDefaultDisplay().getHeight();// 获取窗体高度
        final int window_width = wm.getDefaultDisplay().getWidth();
        int tv_height = sp.getInt("tv_height", 0);// FIXME bug
        int tv_left = sp.getInt("tv_left", 0);
        // /int tv_right = sp.getInt("tv_right", 0);
        if (tv_height != 0) {
            Log.i(TAG, "iv在上方,tv跑下去");
            if (top < (window_height / 2 - tv_height / 2)) { // iv_dragview.getHeight()
                LayoutParams tv_params = (LayoutParams) tv_dragview.getLayoutParams();
                tv_params.topMargin = window_height-tv_height-40;
                // tv_params.bottomMargin = window_height-40;//这个不要,否则显示不正确
                tv_params.leftMargin = tv_left;
                // tv_params.rightMargin = tv_right;//这个不要,否则显示不正确
            }
        }
 
        // 重新设置iv_dragview布局参数
        iv_dragview.setLayoutParams(iv_params);
 
        iv_dragview.setOnTouchListener(new OnTouchListener() {
 
            float startX = 0;
            float startY = 0;
 
            @Override
            public boolean onTouch(View v, MotionEvent event) {
 
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:// 1、触摸按下,记住触摸的起始位置
                    startX = event.getRawX();
                    startY = event.getRawY();
                    break;
                case MotionEvent.ACTION_MOVE:// 2、移动,获取位置,并重新设置起始位置
 
                    // 当前的位置
                    float nowX = event.getRawX();
                    float nowY = event.getRawY();
 
                    // 当前位置减去起始位置,移动的距离
                    float dx = nowX - startX;
                    float dy = nowY - startY;
 
                    int left = (int) (iv_dragview.getLeft() + dx);// 最左边
                    int right = (int) (iv_dragview.getRight() + dx);// 最右边
                    int top = (int) (iv_dragview.getTop() + dy);// 最上边
                    int bottom = (int) (iv_dragview.getBottom() + dy);// 最底边
 
                    // 7、判断,不让移出去边框
                    if (left < 0 || right > window_width || top < 0 || bottom > window_height-iv_dragview.getHeight()) {
                        break;
                    }
 
                    // 8、设置iv_dragview在手机屏幕上半部分,tv_dragview在下面;iv_dragview在下半部分,tv_dragview在上面
                    int tv_height = tv_dragview.getHeight();
                    Editor edit = sp.edit();
                    edit.putInt("tv_height", tv_height);// textview高度,
                    edit.putInt("tv_left", tv_dragview.getLeft());// textview左边距
                    edit.putInt("tv_right", tv_dragview.getRight());// textview右边距
                    edit.commit();
                    if (top < (window_height / 2 - iv_dragview.getHeight() / 2)) {// 当前iv_dragview的最上边top在窗体的上半部分,tv_dragview到底部
                        tv_dragview.layout(tv_dragview.getLeft(), window_height-tv_height-40, tv_dragview.getRight(), window_height-40);
                    } else if (bottom > (window_height / 2 + iv_dragview.getHeight() / 2)) {// 当前iv_dragview的最下边bottom在窗体的下半部分,tv_dragview到顶部
                        tv_dragview.layout(tv_dragview.getLeft(), 0, tv_dragview.getRight(), tv_height);
                    }
 
                    iv_dragview.layout(left, top, right, bottom);// 重新设置iv_dragview的位置
 
                    startX = left;
                    startY = top;
                    break;
                case MotionEvent.ACTION_UP:// 3、松手瞬间,将最后位置保存起来
                    // 获取松手前的位置
                    int lastLeft = iv_dragview.getLeft();
                    int lastTop = iv_dragview.getTop();
                    Editor editor = sp.edit();
                    editor.putInt("left", lastLeft).putInt("top", lastTop);
                    editor.commit();
                    break;
                }
                return true;// 要返回true,才能consume消耗所有的事件
            }
        });
    }
}
问题1:
在Activity中的onCreate()方法中,View对象的宽度,高度还没有计算出来,值为0。
View对象要想被渲染出来,只有当view对象被new出来,然后执行onMeasure()方法后-计算宽度和高度
int height = iv_dragview.getBottom() - iv_dragview.getTop();// iv_dragview高度,值为0
int width = iv_dragview.getRight() - iv_dragview.getLeft();// iv_dragview宽度,值为0
// layout()是布局机制的第二个阶段,第一个阶段还是测量,只有测量后该方法才会生效
iv_dragview.layout(left, top, left + width, top + height);  
问题2:
如果将 拖动到每个边框,第二次再进来的时候,会变的很小,这次因为,当到边框的时候,系统检测显示不出来完整,就将按钮缩小了。
解决:不准拖动至手机边框外