赞
踩
这些天,项目里加了一个功能效果,场景是: 假如有一个家居图片,图片里,有各样的家居用品: 桌子,毛巾,花瓶等等,需要在指定的商品处添加标记,方便用户直接看到商品,点击该标记,可以进入到商品详情页 。实现的效果图如下:
要实现如上效果,有两个思路。
思路1,通过addView,在容器(如FrameLayout)的特定位置,添加标记组件,同事在将ImageView页添加进容器中,保证容器的大小和ImageView的大小相同,这样可以确认标记点的位置不会出现错差。
思路2,通过绘制Bitmap,将背景图片和标记点绘制成同一张图片。
比较两种方法,思路2有些不太妥的地方,1是不好实现标记图标的点击事件;2是不太容易扩展,比如标记点不仅仅是一个图片,而是一个弹框组件,有图有文。 所以,考虑再三后,决定选择第一种实现方式。
1. 自定义布局,包含放置标记图标的容器及显示底部图片的ImageView。
- <?xml version="1.0" encoding="utf-8"?>
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <ImageView
- android:id="@+id/imgBg"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:adjustViewBounds="true"
- android:maxHeight="1000dp"
- android:scaleType="centerCrop" />
-
- <FrameLayout
- android:id="@+id/layouPoints"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center" />
-
- </FrameLayout>
- import android.content.Context;
- import android.graphics.drawable.AnimationDrawable;
- import android.util.AttributeSet;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.FrameLayout;
- import android.widget.ImageView;
- import android.widget.LinearLayout;
- import android.widget.Toast;
-
- import com.bumptech.glide.Glide;
- import com.lnyp.imgdots.R;
- import com.lnyp.imgdots.bean.PointSimple;
-
- import java.util.ArrayList;
-
- public class ImageLayout extends FrameLayout implements View.OnClickListener {
-
- ArrayList<PointSimple> points;
-
- FrameLayout layouPoints;
-
- ImageView imgBg;
-
- Context mContext;
-
- public ImageLayout(Context context) {
- this(context, null);
- }
-
- public ImageLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ImageLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
-
- initView(context, attrs);
- }
-
-
- private void initView(Context context, AttributeSet attrs) {
-
- mContext = context;
-
- View imgPointLayout = inflate(context, R.layout.layout_imgview_point, this);
-
- imgBg = (ImageView) imgPointLayout.findViewById(R.id.imgBg);
- layouPoints = (FrameLayout) imgPointLayout.findViewById(R.id.layouPoints);
- }
-
- public void setImgBg(int width, int height, String imgUrl) {
-
- ViewGroup.LayoutParams lp = imgBg.getLayoutParams();
- lp.width = width;
- lp.height = height;
-
- imgBg.setLayoutParams(lp);
-
- ViewGroup.LayoutParams lp1 = layouPoints.getLayoutParams();
- lp1.width = width;
- lp1.height = height;
-
- layouPoints.setLayoutParams(lp1);
-
- Glide.with(mContext).load(imgUrl).asBitmap().into(imgBg);
-
- addPoints(width, height);
-
- }
-
- public void setPoints(ArrayList<PointSimple> points) {
-
- this.points = points;
- }
-
- private void addPoints(int width, int height) {
-
- layouPoints.removeAllViews();
-
- for (int i = 0; i < points.size(); i++) {
-
- double width_scale = points.get(i).width_scale;
- double height_scale = points.get(i).height_scale;
-
-
- LinearLayout view = (LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.layout_img_point, this, false);
- ImageView imageView = (ImageView) view.findViewById(R.id.imgPoint);
- imageView.setTag(i);
-
- AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
- animationDrawable.start();
-
- LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
-
- layoutParams.leftMargin = (int) (width * width_scale);
- layoutParams.topMargin = (int) (height * height_scale);
-
- imageView.setOnClickListener(this);
-
- layouPoints.addView(view, layoutParams);
- }
- }
-
-
- @Override
- public void onClick(View view) {
- int pos = (int) view.getTag();
- Toast.makeText(getContext(), "pos : " + pos, Toast.LENGTH_SHORT).show();
- }
- }
来看看ImageLayout源码,里面有两个重要的方法:
·public void setImgBg(int width, int height, String imgUrl) 该方法主要根据图片的大小,设置标记图容器的大小,然后加载背景图。
·private void addPoints(int width, int height) 该方法主要向记图容器中添加标记图。
3.PointSimple.java
- public class PointSimple {
-
- // 标记点相对于横向的宽度的比例
- public double width_scale;
- // 标记点相对于横向的高度的比例
- public double height_scale;
-
- }
4.1 首先,准备一些测试数据
- private void initData() {
-
- imgSimples = new ArrayList<>();
-
- ImgSimple imgSimple1 = new ImgSimple();
- imgSimple1.url = "http://o79w6dswy.bkt.clouddn.com/img5.png";
- imgSimple1.scale = 1.6f;
-
- ArrayList<PointSimple> pointSimples = new ArrayList<>();
- PointSimple pointSimple1 = new PointSimple();
- pointSimple1.width_scale = 0.36f;
- pointSimple1.height_scale = 0.75f;
-
- PointSimple pointSimple2 = new PointSimple();
- pointSimple2.width_scale = 0.64f;
- pointSimple2.height_scale = 0.5f;
-
-
- PointSimple pointSimple3 = new PointSimple();
- pointSimple3.width_scale = 0.276f;
- pointSimple3.height_scale = 0.764f;
-
- PointSimple pointSimple4 = new PointSimple();
- pointSimple4.width_scale = 0.638f;
- pointSimple4.height_scale = 0.74f;
-
- PointSimple pointSimple5 = new PointSimple();
- pointSimple5.width_scale = 0.796f;
- pointSimple5.height_scale = 0.526f;
-
- PointSimple pointSimple6 = new PointSimple();
- pointSimple6.width_scale = 0.486f;
- pointSimple6.height_scale = 0.364f;
-
- pointSimples.add(pointSimple1);
- pointSimples.add(pointSimple2);
- pointSimples.add(pointSimple3);
- pointSimples.add(pointSimple4);
- pointSimples.add(pointSimple5);
- pointSimples.add(pointSimple6);
-
- imgSimple1.pointSimples = pointSimples;
-
-
- ImgSimple imgSimple2 = new ImgSimple();
- imgSimple2.url = "http://o79w6dswy.bkt.clouddn.com/img3.png";
- imgSimple2.scale = 1.6f;
-
- ArrayList<PointSimple> pointSimples2 = new ArrayList<>();
- PointSimple pointSimple7 = new PointSimple();
- pointSimple7.width_scale = 0.36f;
- pointSimple7.height_scale = 0.75f;
-
- PointSimple pointSimple8 = new PointSimple();
- pointSimple8.width_scale = 0.64f;
- pointSimple8.height_scale = 0.5f;
-
-
- PointSimple pointSimple9 = new PointSimple();
- pointSimple9.width_scale = 0.276f;
- pointSimple9.height_scale = 0.764f;
-
-
- pointSimples2.add(pointSimple7);
- pointSimples2.add(pointSimple8);
- pointSimples2.add(pointSimple9);
-
- imgSimple2.pointSimples = pointSimples2;
-
-
- ImgSimple imgSimple3 = new ImgSimple();
- imgSimple3.url = "http://o79w6dswy.bkt.clouddn.com/421428.jpg";
- imgSimple3.scale = 0.75f;
-
- ArrayList<PointSimple> pointSimples3 = new ArrayList<>();
- PointSimple pointSimple11 = new PointSimple();
- pointSimple11.width_scale = 0.1f;
- pointSimple11.height_scale = 0.3f;
-
- PointSimple pointSimple12 = new PointSimple();
- pointSimple12.width_scale = 0.3f;
- pointSimple12.height_scale = 0.5f;
-
-
- PointSimple pointSimple13 = new PointSimple();
- pointSimple13.width_scale = 0.5f;
- pointSimple13.height_scale = 0.8f;
-
-
- pointSimples3.add(pointSimple11);
- pointSimples3.add(pointSimple12);
- pointSimples3.add(pointSimple13);
-
- imgSimple3.pointSimples = pointSimples3;
-
- imgSimples.add(imgSimple1);
- imgSimples.add(imgSimple2);
- imgSimples.add(imgSimple3);
- }
- import android.app.Activity;
- import android.support.v4.view.PagerAdapter;
- import android.support.v4.view.ViewPager;
- import android.util.DisplayMetrics;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.LinearLayout;
-
- import com.lnyp.imgdots.R;
- import com.lnyp.imgdots.bean.ImgSimple;
- import com.lnyp.imgdots.bean.PointSimple;
- import com.lnyp.imgdots.view.ImageLayout;
-
- import java.util.ArrayList;
- import java.util.List;
-
- public class ImgBrowsePagerAdapter extends PagerAdapter {
-
- List<ImgSimple> imgSimples;
-
- List<View> views;
-
- Activity mContext;
-
- private int width;
-
- public ImgBrowsePagerAdapter(Activity context, List<ImgSimple> imgSimples) {
-
- this.mContext = context;
- this.imgSimples = imgSimples;
-
- this.views = new ArrayList<>();
-
- DisplayMetrics dm = new DisplayMetrics();
- context.getWindowManager().getDefaultDisplay().getMetrics(dm);
-
- width = dm.widthPixels;
- }
-
- @Override
- public int getCount() { // 获得size
- return imgSimples.size();
- }
-
- @Override
- public boolean isViewFromObject(View arg0, Object arg1) {
- return arg0 == arg1;
- }
-
- @Override
- public void destroyItem(ViewGroup container, int position, Object object) {
-
- ((ViewPager) container).removeView((View) object);
- }
-
- @Override
- public Object instantiateItem(ViewGroup container, int position) {
-
- LinearLayout view = (LinearLayout) LayoutInflater.from(mContext).inflate(R.layout.layout_img_browse, null);
- ImageLayout layoutContent = (ImageLayout) view.findViewById(R.id.layoutContent);
-
- try {
-
- String imgUrl = imgSimples.get(position).url;
- float scale = imgSimples.get(position).scale;
- ArrayList<PointSimple> pointSimples = imgSimples.get(position).pointSimples;
-
- layoutContent.setPoints(pointSimples);
-
- int height = (int) (width * scale);
-
- layoutContent.setImgBg(width, height, imgUrl);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- ((ViewPager) container).addView(view);
-
- return view;
- }
- }
4.3 适配器的布局文件layout_img_browse.xml,其中包含了上方自定义的组件ImageLayout
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:orientation="vertical">
-
- <com.lnyp.imgdots.view.ImageLayout
- android:id="@+id/layoutContent"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true" />
-
- </LinearLayout>
通过加载了布局文件,获取ImageLayout对象; 然后,有了这个对象,及计算出的height和width,我们就可以动态的添加背景图及标记物的位置。
因为图片是经过等比缩放的,而标记物的位置是相对于图片的,所以在相同大小的容器添加标记物,它的位置不会出现偏差。
通过以上几步,便可以实现前面动态图中的功能效果了。
如有疑问或建议,欢迎进QQ群讨论:487786925( Android研发村 )
项目github地址:https://github.com/zuiwuyuan/ImgDots
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。