仿百度智能导诊页面

首先介绍一下功能:点击人体部位实现微交互,并进行页面跳转。


此功能共有三类人,男人女人和小孩,同时又结合了前身,后背,及头部放大,故有3*3种情况,这里我们使用自定义View去解决。


首先我们自定义一个BodyView继承于View。


  1. public BodyView(Context context) {
  2. this(context, null);
  3. }
  4. public BodyView(Context context, AttributeSet paramAttributeSet) {
  5. this(context, paramAttributeSet, 0);
  6. }
  7. public BodyView(Context context, AttributeSet paramAttributeSet, int paramInt) {
  8. super(context, paramAttributeSet, paramInt);
  9. this.mContext = context;
  10. init();
  11. }

一、首先我们在init()方法中做一些初始化

  1. private void init() {
  2. float density = getResources().getDisplayMetrics().density;
  3. BitmapFactory.Options localOptions = new BitmapFactory.Options();
  4. localOptions.inJustDecodeBounds = true;
  5. BitmapFactory.decodeResource(getResources(), R.mipmap.man_front, localOptions);
  6. mManFrontWidth = ((int) (density * localOptions.outWidth / 2.0F));
  7. mManFrontHeight = ((int) (density * localOptions.outHeight / 2.0F));
  8. BitmapFactory.decodeResource(getResources(), R.mipmap.man_bigface, localOptions);
  9. mHeadWidth = ((int) (density * localOptions.outWidth / 2.0F));
  10. mHeadHeight = ((int) (density * localOptions.outHeight / 2.0F));
  11. mPaint = new Paint();
  12. mPaint.setAntiAlias(true);
  13. mPaint.setColor(Color.WHITE);
  14. mPaint.setStrokeWidth(5.0F);
  15. mInitAreaRunnable = new InitAreaRunnable(this);
  16. }
我们做的是drawBitmap,这里是对图片和画笔做一些设置,其中关键的是我们创建了一个子线程,通过runnable我们可以读取一些坐标及偏移量的数据


二、接下来我们看看我们创建的Runnable做了些什么:

  1. switch (mCrowd.ordinal()) {
  2. case 1:
  3. if (mIsHead) {
  4. if (mManHeadAreaList.size() == 0 || isCache) {
  5. mCurrentAreaList = getBodyAreaFromFile("guideBody/man_bigface", true);
  6. }
  7. } else if (mIsBack) {
  8. if (mManBackAreaList.size() == 0 || isCache) {
  9. mCurrentAreaList = getBodyAreaFromFile("guideBody/man_back", false);
  10. }
  11. } else {
  12. if (mManFrontAreaList.size() == 0 || isCache) {
  13. mCurrentAreaList = getBodyAreaFromFile("guideBody/man_front", false);
  14. }
  15. }
  16. break;
  17. case 2:
  18. if (mIsHead) {
  19. if (mWomanHeadAreaList.size() == 0 || isCache) {
  20. mCurrentAreaList = getBodyAreaFromFile("guideBody/woman_bigface", true);
  21. }
  22. } else if (mIsBack) {
  23. if (mWomanBackAreaList.size() == 0 || isCache) {
  24. mCurrentAreaList = getBodyAreaFromFile("guideBody/woman_back", false);
  25. }
  26. } else {
  27. if (mWomanFrontAreaList.size() == 0 || isCache) {
  28. mCurrentAreaList = getBodyAreaFromFile("guideBody/woman_front", false);
  29. }
  30. }
  31. break;
  32. case 3:
  33. if (mIsHead) {
  34. if (mKidHeadAreaList.size() == 0 || isCache) {
  35. mCurrentAreaList = getBodyAreaFromFile("guideBody/kid_bigface", true);
  36. }
  37. } else if (mIsBack) {
  38. if (mKidBackAreaList.size() == 0 || isCache) {
  39. mCurrentAreaList = getBodyAreaFromFile("guideBody/kid_back", false);
  40. }
  41. } else {
  42. if (mKidFrontAreaList.size() == 0 || isCache) {
  43. mCurrentAreaList = getBodyAreaFromFile("guideBody/kid_front", false);
  44. }
  45. }
  46. }
先不管switch case语句,我们在这里读取了File文件保存的位图的偏移量和有效点击区域的数据。

方法如下:

  1. private List getBodyAreaFromFile(String paramString, boolean isHead) {
  2. ArrayList bodyAreaList = new ArrayList();
  3. try {
  4. JSONArray localJSONArray1 = new JSONArray(new FileUtil().readFromAssets(paramString));
  5. for (int i = 0; i < localJSONArray1.length(); i++) {
  6. JSONObject localJSONObject1 = localJSONArray1.optJSONObject(i);
  7. BodyArea bodyArea = new BodyArea();
  8. if (localJSONObject1 != null) {
  9. bodyArea.bodyId = localJSONObject1.optInt("bid");
  10. bodyArea.mipmapId = getResources().getIdentifier("intelligence_highlight_0" + String.valueOf(bodyArea.bodyId), "mipmap", getContext().getPackageName());
  11. bodyArea.bodyPart = BodyPart.values()[(bodyArea.bodyId % 100)];
  12. }
  13. JSONObject localJSONObject2 = localJSONObject1.optJSONObject("offset");
  14. if (localJSONObject2 != null) {
  15. bodyArea.areaPoint = new AreaPoint(this, localJSONObject2.optInt("x"), localJSONObject2.optInt("y"), isHead);
  16. }
  17. JSONArray localJSONArray2 = localJSONObject1.optJSONArray("polygon");
  18. for (int j = 0; j < localJSONArray2.length(); j++) {
  19. JSONObject localJSONObject3 = localJSONArray2.optJSONObject(j);
  20. if (localJSONObject3 != null) {
  21. AreaPoint areaPoint = new AreaPoint(this, localJSONObject3.optInt("x"), localJSONObject3.optInt("y"), isHead);
  22. bodyArea.partPolygon.add(areaPoint);
  23. }
  24. }
  25. bodyAreaList.add(bodyArea);
  26. }
  27. } catch (JSONException e) {
  28. e.printStackTrace();
  29. }
  30. return bodyAreaList;
  31. }


三、解析Json,并封装成对象。

  1. /**
  2. * 热区对象
  3. */
  4. class BodyArea {
  5. public int bodyId = 0;
  6. public int mipmapId = R.mipmap.google;
  7. public BodyPart bodyPart = BodyPart.HEAD;
  8. public AreaPoint areaPoint = new AreaPoint();
  9. public List partPolygon = new ArrayList();
  10. public String toString() {
  11. return "{bodyId=" + bodyId + ",mipmapId=" + mipmapId + ",bodyPart=" + bodyPart.toString() + "}";
  12. }
  13. }
我们对用户的触摸点击称之为热区,当然热区是个范围值,这里我们用一个List 分装了他们的边界


四、监听用户的onTouchEvent事件

  1. @Override
  2. public boolean onTouchEvent(MotionEvent event) {
  3. if (!this.mEnableFlag) {
  4. return super.onTouchEvent(event);
  5. }
  6. switch (event.getAction()) {
  7. case MotionEvent.ACTION_DOWN:
  8. case MotionEvent.ACTION_MOVE:
  9. mXDown = event.getX();
  10. mYDown = event.getY();
  11. parseTouchEvent(new Point((int) mXDown, (int) mYDown));
  12. break;
  13. case MotionEvent.ACTION_UP:
  14. onActionUp();
  15. break;
  16. }
  17. return true;
  18. }

在这里我们通过一个算法去计算用户触摸的点是否在矩阵内,

  1. private void parseTouchEvent(Point point) {
  2. if (mCurrentAreaList != null) {
  3. Iterator iterator = mCurrentAreaList.iterator();
  4. while (iterator.hasNext()) {
  5. BodyArea bodyArea = iterator.next();
  6. if (bodyArea.partPolygon != null && isPointInPolygon(point, bodyArea.partPolygon)) {
  7. mCurrentBodyArea = bodyArea;
  8. invalidate();
  9. break;
  10. } else {
  11. mCurrentBodyArea = null;
  12. invalidate();
  13. }
  14. }
  15. }
  16. }
根据用户的点击重绘界面。





你可能感兴趣的:(UI,交互)