菜鸟进场,方圆十里,寸草不生
今天有一个需求,实现一个标注功能,就是类似于地图开发上的一个marker,只不过背景采用自己上传的图片,然后marker还要实现可以拖拽的功能,大概实现的功能就是这样的:
废话不多说,先说原理,再上代码。
原理:
1、覆盖物图片的拖动:这个简单嘛,网上代码一抓一大把,重点在于初始化相对于图片的位置。
2、覆盖物图片如何跟随背景图移动:利用photoview的放大缩小功能,通过photoview自带的监听来返回图片当前位置信息,然后根据当前的位置来动态设置覆盖物的位置。
好吧,我觉得我也没说清楚。直接上代码!
/**
* @author zx
* @date 2018/10/30/030 17:29
* email 1058083107@qq.com
* description 图片标注
*/
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
@BindView(R.id.bt_wind)
Button btWind;
@BindView(R.id.bt_shade)
Button btShade;
@BindView(R.id.bt_rain)
Button btRain;
@BindView(R.id.bt_sun)
Button btSun;
@BindView(R.id.rl_map)
RelativeLayout rlMap;
@BindView(R.id.iv_map)
PhotoView ivMap;
@BindView(R.id.iv_reset)
ImageView ivReset;
/**
* 存放动态添加的标注图片
*/
private List<ImageView> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
DensityUtil.init(this);
setListener();
}
private void setListener() {
/**
* 设置复位监听
*/
ivReset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* 恢复放大倍数(好像photoview不能缩小)
*/
ivMap.setScale(1);
}
});
/**
* photoview图片移动监听(这个返回的位置是背景图相对于左上角与屏幕的相对距离)
*/
ivMap.setOnMatrixChangeListener(new PhotoViewAttacher.OnMatrixChangedListener() {
@Override
public void onMatrixChanged(RectF rect) {
for (int i = 0; i < list.size(); i++) {
ImageView imageView = list.get(i);
WeatherBean bean = (WeatherBean) imageView.getTag();
if (imageView != null) {
//原始的相对位置乘当前的放大倍数再加上偏移量即当前的相对位置
imageView.setX(bean.getPointX() * ivMap.getScale() + rect.left);
imageView.setY(bean.getPointY() * ivMap.getScale() + rect.top);
}
}
}
});
}
/**
* 点击显示不同的图标,可以对应以后的指示灯什么的
*
* @param view
*/
@OnClick({R.id.bt_wind, R.id.bt_shade, R.id.bt_rain, R.id.bt_sun})
public void onViewClicked(View view) {
ImageView imageView = new ImageView(this);
WeatherBean bean = new WeatherBean();
switch (view.getId()) {
case R.id.bt_wind:
imageView.setImageResource(R.mipmap.wind);
bean.setKind(1);
break;
case R.id.bt_shade:
bean.setKind(2);
imageView.setImageResource(R.mipmap.shade);
break;
case R.id.bt_rain:
bean.setKind(3);
imageView.setImageResource(R.mipmap.rain);
break;
case R.id.bt_sun:
bean.setKind(4);
imageView.setImageResource(R.mipmap.sun);
break;
default:
}
imageView.setOnTouchListener(this);
//不管图片有没有放大,新添加的图标永远出现在右上角
bean.setPointX(0 - ivMap.getDisplayRect().left);
bean.setPointY(0 - ivMap.getDisplayRect().top);
imageView.setTag(bean);
list.add(imageView);
rlMap.addView(imageView);
}
/**
* 这个是用来计算手指移动距离的
*/
float oldX = 0;
float oldY = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
oldX = event.getRawX();
oldY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
//让控件跟着自己的手指动
v.setX(v.getX() + event.getRawX() - oldX);
v.setY(v.getY() + event.getRawY() - oldY);
oldX = event.getRawX();
oldY = event.getRawY();
break;
case MotionEvent.ACTION_UP:
//如果在删除区域,就把他给删除掉
if (v.getX() > DensityUtil.screenWidth - DensityUtil.dip2px(50) && v.getY() < DensityUtil.dip2px(50)) {
rlMap.removeView(v);
}
WeatherBean bean = (WeatherBean) v.getTag();
RectF rectF = ivMap.getDisplayRect();
//计算相对于photoview左边定点的相对位置
bean.setPointX((v.getX() - rectF.left) / ivMap.getScale());
bean.setPointY((v.getY() - rectF.top) / ivMap.getScale());
break;
default:
}
return true;
}
}
注释在代码里,就是相对位置的计算,感觉我越解释越乱,反正大概也就这么回事儿…
如果有什么不懂的地方,爱莫能助啊。