Android 高仿微信头像截取 打造不一样的自定义控件

来源:互联网 发布:淘宝运营助理招聘要求 编辑:程序博客网 时间:2024/06/10 12:35
转载请表明出处:http://blog.csdn.net/lmj623565791/article/details/39761281,本文出自:【张鸿洋的博客】

1、概述

前面已经写了关于检测手势识别的文章,如果不了解可以参考:Android 手势检测实战 打造支持缩放平移的图片预览效果(下)。首先本篇文章,将对之前博客的ZoomImageView代码进行些许的修改与改善,然后用到我们的本篇博客中去,实现仿微信的头像截取功能,当然了,个人觉得微信的截取头像功能貌似做得不太好,本篇博客准备去其糟粕,取其精华;最后还会见识到不一样的自定义控件的方式,也是在本人博客中首次出现,如果有兴趣可以读完本篇博客,希望可以启到抛砖引玉的效果。

2、效果分析

1、效果图:


我们来看看妹子的项链,嗯,妹子项链还是不错的~

2、效果分析

根据上面的效果,我们目测需要自定义两个控件,一个就是我们的可自由缩放移动的ImageView,一个就是那个白色的边框;然后一起放置到一个RelativeLayout中;最后对外公布一个裁剪的方法,返回一个Bitmap;

暂时的分析就这样,下面我们来写代码~

首先是白色框框那个自定义View,我们叫做ClipImageBorderView

3、ClipImageBorderView

分析下这个View,其实就是根据在屏幕中绘制一个正方形,正方形区域以外为半透明,绘制这个正方形需要与屏幕左右边距有个边距。

我们准备按如下图绘制:


按顺序在View的onDraw里面绘制上图中:1、2、3、4,四个半透明的区域,然后在中间正方形区域绘制一个正方形

下面看下代码:

[java] view plain copy
  1. package com.zhy.view;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Canvas;  
  5. import android.graphics.Color;  
  6. import android.graphics.Paint;  
  7. import android.graphics.Paint.Style;  
  8. import android.util.AttributeSet;  
  9. import android.util.TypedValue;  
  10. import android.view.View;  
  11. /** 
  12.  * @author zhy 
  13.  * 
  14.  */  
  15. public class ClipImageBorderView extends View  
  16. {  
  17.     /** 
  18.      * 水平方向与View的边距 
  19.      */  
  20.     private int mHorizontalPadding = 20;  
  21.     /** 
  22.      * 垂直方向与View的边距 
  23.      */  
  24.     private int mVerticalPadding;  
  25.     /** 
  26.      * 绘制的矩形的宽度 
  27.      */  
  28.     private int mWidth;  
  29.     /** 
  30.      * 边框的颜色,默认为白色 
  31.      */  
  32.     private int mBorderColor = Color.parseColor("#FFFFFF");  
  33.     /** 
  34.      * 边框的宽度 单位dp 
  35.      */  
  36.     private int mBorderWidth = 1;  
  37.   
  38.     private Paint mPaint;  
  39.   
  40.     public ClipImageBorderView(Context context)  
  41.     {  
  42.         this(context, null);  
  43.     }  
  44.   
  45.     public ClipImageBorderView(Context context, AttributeSet attrs)  
  46.     {  
  47.         this(context, attrs, 0);  
  48.     }  
  49.   
  50.     public ClipImageBorderView(Context context, AttributeSet attrs, int defStyle)  
  51.     {  
  52.         super(context, attrs, defStyle);  
  53.         // 计算padding的px  
  54.         mHorizontalPadding = (int) TypedValue.applyDimension(  
  55.                 TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding, getResources()  
  56.                         .getDisplayMetrics());  
  57.         mBorderWidth = (int) TypedValue.applyDimension(  
  58.                 TypedValue.COMPLEX_UNIT_DIP, mBorderWidth, getResources()  
  59.                         .getDisplayMetrics());  
  60.         mPaint = new Paint();  
  61.         mPaint.setAntiAlias(true);  
  62.     }  
  63.   
  64.     @Override  
  65.     protected void onDraw(Canvas canvas)  
  66.     {  
  67.         super.onDraw(canvas);  
  68.         //计算矩形区域的宽度  
  69.         mWidth = getWidth() - 2 * mHorizontalPadding;  
  70.         //计算距离屏幕垂直边界 的边距  
  71.         mVerticalPadding = (getHeight() - mWidth) / 2;  
  72.         mPaint.setColor(Color.parseColor("#aa000000"));  
  73.         mPaint.setStyle(Style.FILL);  
  74.         // 绘制左边1  
  75.         canvas.drawRect(00, mHorizontalPadding, getHeight(), mPaint);  
  76.         // 绘制右边2  
  77.         canvas.drawRect(getWidth() - mHorizontalPadding, 0, getWidth(),  
  78.                 getHeight(), mPaint);  
  79.         // 绘制上边3  
  80.         canvas.drawRect(mHorizontalPadding, 0, getWidth() - mHorizontalPadding,  
  81.                 mVerticalPadding, mPaint);  
  82.         // 绘制下边4  
  83.         canvas.drawRect(mHorizontalPadding, getHeight() - mVerticalPadding,  
  84.                 getWidth() - mHorizontalPadding, getHeight(), mPaint);  
  85.         // 绘制外边框  
  86.         mPaint.setColor(mBorderColor);  
  87.         mPaint.setStrokeWidth(mBorderWidth);  
  88.         mPaint.setStyle(Style.STROKE);  
  89.         canvas.drawRect(mHorizontalPadding, mVerticalPadding, getWidth()  
  90.                 - mHorizontalPadding, getHeight() - mVerticalPadding, mPaint);  
  91.   
  92.     }  
  93.   
  94. }  
我们直接预设了一个水平方向的边距,根据边距计算出正方形的边长,接下来就是按照上图分别会1、2、3、4四个区域,最后就是绘制我们的正方形~~

代码还是很简单的~~我们的ClipImageBorderView就搞定了,我们决定来测试一下:

布局文件:

[html] view plain copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="@drawable/a"   >  
  6.   
  7.     <com.zhy.view.ClipImageBorderView  
  8.         android:id="@+id/id_clipImageLayout"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="fill_parent" />  
  11.   
  12. </RelativeLayout>  

效果图:


故意放了个背景,没撒用,就是为了能看出效果,可以看到我们的框框绘制的还是蛮不错的~~嗯,这个框框距离屏幕左右两侧的距离应该抽取出来,嗯,后面再说~

4、ClipZoomImageView

我们准备对我们原先的ZoomImageView进行简单的修改,修改的地方:
1、在onGlobalLayout方法中,如果图片的宽或者高只要一个小于我们的正方形的边长,我们会直接把较小的尺寸放大至正方形的边长;如果图片的宽和高都大于我们的正方形的边长,我们仅仅把图片移动到我们屏幕的中央,不做缩放处理;

2、根据步骤1,我们会获得初始的缩放比例(默认为1.0f),然后SCALE_MID , 与 SCALE_MAX 分别为2倍和4倍的初始化缩放比例。

3、图片在移动过程中的边界检测完全根据正方形的区域,图片不会在移动过程中与正方形区域产生内边距

4、对外公布一个裁切的方法

部分代码:

[java] view plain copy
  1. /** 
  2.      * 水平方向与View的边距 
  3.      */  
  4.     private int mHorizontalPadding = 20;  
  5.     /** 
  6.      * 垂直方向与View的边距 
  7.      */  
  8.     private int mVerticalPadding;  
  9.   
  10.     @Override  
  11.     public void onGlobalLayout()  
  12.     {  
  13.         if (once)  
  14.         {  
  15.             Drawable d = getDrawable();  
  16.             if (d == null)  
  17.                 return;  
  18.             Log.e(TAG, d.getIntrinsicWidth() + " , " + d.getIntrinsicHeight());  
  19.             // 计算padding的px  
  20.             mHorizontalPadding = (int) TypedValue.applyDimension(  
  21.                     TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding,  
  22.                     getResources().getDisplayMetrics());  
  23.             // 垂直方向的边距  
  24.             mVerticalPadding = (getHeight() - (getWidth() - 2 * mHorizontalPadding)) / 2;  
  25.   
  26.             int width = getWidth();  
  27.             int height = getHeight();  
  28.             // 拿到图片的宽和高  
  29.             int dw = d.getIntrinsicWidth();  
  30.             int dh = d.getIntrinsicHeight();  
  31.             float scale = 1.0f;  
  32.             if (dw < getWidth() - mHorizontalPadding * 2  
  33.                     && dh > getHeight() - mVerticalPadding * 2)  
  34.             {  
  35.                 scale = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw;  
  36.             }  
  37.   
  38.             if (dh < getHeight() - mVerticalPadding * 2  
  39.                     && dw > getWidth() - mHorizontalPadding * 2)  
  40.             {  
  41.                 scale = (getHeight() * 1.0f - mVerticalPadding * 2) / dh;  
  42.             }  
  43.   
  44.             if (dw < getWidth() - mHorizontalPadding * 2  
  45.                     && dh < getHeight() - mVerticalPadding * 2)  
  46.             {  
  47.                 float scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2)  
  48.                         / dw;  
  49.                 float scaleH = (getHeight() * 1.0f - mVerticalPadding * 2) / dh;  
  50.                 scale = Math.max(scaleW, scaleH);  
  51.             }  
  52.   
  53.             initScale = scale;  
  54.             SCALE_MID = initScale * 2;  
  55.             SCALE_MAX = initScale * 4;  
  56.             Log.e(TAG, "initScale = " + initScale);  
  57.             mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);  
  58.             mScaleMatrix.postScale(scale, scale, getWidth() / 2,  
  59.                     getHeight() / 2);  
  60.             // 图片移动至屏幕中心  
  61.             setImageMatrix(mScaleMatrix);  
  62.             once = false;  
  63.         }  
  64.   
  65.     }  
  66.   
  67.     /** 
  68.      * 剪切图片,返回剪切后的bitmap对象 
  69.      *  
  70.      * @return 
  71.      */  
  72.     public Bitmap clip()  
  73.     {  
  74.         Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),  
  75.                 Bitmap.Config.ARGB_8888);  
  76.         Canvas canvas = new Canvas(bitmap);  
  77.         draw(canvas);  
  78.         return Bitmap.createBitmap(bitmap, mHorizontalPadding,  
  79.                 mVerticalPadding, getWidth() - 2 * mHorizontalPadding,  
  80.                 getWidth() - 2 * mHorizontalPadding);  
  81.     }  
  82.       
  83.     /** 
  84.      * 边界检测 
  85.      */  
  86.     private void checkBorder()  
  87.     {  
  88.   
  89.         RectF rect = getMatrixRectF();  
  90.         float deltaX = 0;  
  91.         float deltaY = 0;  
  92.   
  93.         int width = getWidth();  
  94.         int height = getHeight();  
  95.   
  96.         // 如果宽或高大于屏幕,则控制范围  
  97.         if (rect.width() >= width - 2 * mHorizontalPadding)  
  98.         {  
  99.             if (rect.left > mHorizontalPadding)  
  100.             {  
  101.                 deltaX = -rect.left + mHorizontalPadding;  
  102.             }  
  103.             if (rect.right < width - mHorizontalPadding)  
  104.             {  
  105.                 deltaX = width - mHorizontalPadding - rect.right;  
  106.             }  
  107.         }  
  108.         if (rect.height() >= height - 2 * mVerticalPadding)  
  109.         {  
  110.             if (rect.top > mVerticalPadding)  
  111.             {  
  112.                 deltaY = -rect.top + mVerticalPadding;  
  113.             }  
  114.             if (rect.bottom < height - mVerticalPadding)  
  115.             {  
  116.                 deltaY = height - mVerticalPadding - rect.bottom;  
  117.             }  
  118.         }  
  119.         mScaleMatrix.postTranslate(deltaX, deltaY);  
  120.   
  121.     }  

这里贴出了改变的代码,完整的代码就不贴了,太长了,如果大家学习过前面的博客应该也会比较熟悉,若没有也没事,后面会提供源码。

贴代码的目的,第一让大家看下我们改变了哪些;第二,我想暴露出我们代码中的问题,我们设置了一个这样的变量:mHorizontalPadding = 20;这个是手动和ClipImageBorderView里面的成员变量mHorizontalPadding 写的一致,也就是说这个变量,两个自定义的View都需要使用且需要相同的值,目前我们的做法,写死且每个View各自定义一个。这种做法不用说,肯定不好,即使抽取成自定义属性,两个View都需要进行抽取,且用户在使用的时候,还需要设置为一样的值,总觉得有点强人所难~~

5、不一样的自定义控件

现在我们考虑下:易用性。目前为止,其实我们的效果已经实现了,但是需要用户这么写布局文件:

[html] view plain copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="#aaaaaa" >  
  6.   
  7.     <com.zhy.view.ZoomImageView  
  8.         android:id="@+id/id_zoomImageView"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="fill_parent"  
  11.         android:scaleType="matrix"  
  12.         android:src="@drawable/a" />  
  13.   
  14.     <com.zhy.view.ClipImageView  
  15.         android:layout_width="fill_parent"  
  16.         android:layout_height="fill_parent" />  
  17.   
  18. </RelativeLayout>  

然后这两个类中都有一个mHorizontalPadding变量,且值一样,上面也说过,即使抽取成自定义变量,也需要在布局文件中每个View中各写一次。so, we need change . 这样的耦合度太夸张了,且使用起来蹩脚。

于是乎,我决定把这两个控件想办法整到一起,用户使用时只需要声明一个控件:

怎么做呢,我们使用组合的思想来自定义控件,我们再声明一个控件,继承子RelativeLayout,然后在这个自定义RelativeLayout中通过代码添加这两个自定义的布局,并且设置一些公用的属性,具体我们就开始行动。

1、ClipImageLayout

我们自定义一个RelativeLayout叫做ClipImageLayout,用于放置我们的两个自定义View,并且由ClipImageLayout进行设置边距,然后传给它内部的两个View,这样的话,跟用户交互的就一个ClipImageLayout,用户只需要设置一次边距即可。

完整的ClipImageLayout代码:

[java] view plain copy
  1. package com.zhy.view;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Bitmap;  
  5. import android.util.AttributeSet;  
  6. import android.util.TypedValue;  
  7. import android.widget.RelativeLayout;  
  8.   
  9. import com.zhy.clippic.R;  
  10. /** 
  11.  * zhy 
  12.  * @author zhy 
  13.  * 
  14.  */  
  15. public class ClipImageLayout extends RelativeLayout  
  16. {  
  17.   
  18.     private ClipZoomImageView mZoomImageView;  
  19.     private ClipImageBorderView mClipImageView;  
  20.   
  21.     /** 
  22.      * 这里测试,直接写死了大小,真正使用过程中,可以提取为自定义属性 
  23.      */  
  24.     private int mHorizontalPadding = 20;  
  25.   
  26.     public ClipImageLayout(Context context, AttributeSet attrs)  
  27.     {  
  28.         super(context, attrs);  
  29.   
  30.         mZoomImageView = new ClipZoomImageView(context);  
  31.         mClipImageView = new ClipImageBorderView(context);  
  32.   
  33.         android.view.ViewGroup.LayoutParams lp = new LayoutParams(  
  34.                 android.view.ViewGroup.LayoutParams.MATCH_PARENT,  
  35.                 android.view.ViewGroup.LayoutParams.MATCH_PARENT);  
  36.           
  37.         /** 
  38.          * 这里测试,直接写死了图片,真正使用过程中,可以提取为自定义属性 
  39.          */  
  40.         mZoomImageView.setImageDrawable(getResources().getDrawable(  
  41.                 R.drawable.a));  
  42.           
  43.         this.addView(mZoomImageView, lp);  
  44.         this.addView(mClipImageView, lp);  
  45.   
  46.           
  47.         // 计算padding的px  
  48.         mHorizontalPadding = (int) TypedValue.applyDimension(  
  49.                 TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding, getResources()  
  50.                         .getDisplayMetrics());  
  51.         mZoomImageView.setHorizontalPadding(mHorizontalPadding);  
  52.         mClipImageView.setHorizontalPadding(mHorizontalPadding);  
  53.     }  
  54.   
  55.     /** 
  56.      * 对外公布设置边距的方法,单位为dp 
  57.      *  
  58.      * @param mHorizontalPadding 
  59.      */  
  60.     public void setHorizontalPadding(int mHorizontalPadding)  
  61.     {  
  62.         this.mHorizontalPadding = mHorizontalPadding;  
  63.     }  
  64.   
  65.     /** 
  66.      * 裁切图片 
  67.      *  
  68.      * @return 
  69.      */  
  70.     public Bitmap clip()  
  71.     {  
  72.         return mZoomImageView.clip();  
  73.     }  
  74.   
  75. }  

可以看到,现在用户需要使用头像裁切功能只需要声明下ClipImageLayout即可,完全避免了上述我们描述的问题,我们对用户屏蔽了两个真正实现的类。这个也是自定义控件的一种方式,希望可以借此抛砖引玉,大家能够更加合理的设计出自己的控件~~

好了,我们的ClipImageLayout搞定以后,下面看下如何使用~

6、用法

1、布局文件

[html] view plain copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="#aaaaaa"   >  
  6.   
  7.     <com.zhy.view.ClipImageLayout  
  8.         android:id="@+id/id_clipImageLayout"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="fill_parent" />  
  11.   
  12. </RelativeLayout>  

2、MainActivity

[java] view plain copy
  1. package com.zhy.clippic;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.Intent;  
  7. import android.graphics.Bitmap;  
  8. import android.os.Bundle;  
  9. import android.view.Menu;  
  10. import android.view.MenuItem;  
  11.   
  12. import com.zhy.view.ClipImageLayout;  
  13.   
  14. public class MainActivity extends Activity  
  15. {  
  16.     private ClipImageLayout mClipImageLayout;  
  17.   
  18.     @Override  
  19.     protected void onCreate(Bundle savedInstanceState)  
  20.     {  
  21.         super.onCreate(savedInstanceState);  
  22.         setContentView(R.layout.activity_main);  
  23.   
  24.         mClipImageLayout = (ClipImageLayout) findViewById(R.id.id_clipImageLayout);  
  25.   
  26.     }  
  27.   
  28.     @Override  
  29.     public boolean onCreateOptionsMenu(Menu menu)  
  30.     {  
  31.         getMenuInflater().inflate(R.menu.main, menu);  
  32.         return true;  
  33.     }  
  34.   
  35.     @Override  
  36.     public boolean onOptionsItemSelected(MenuItem item)  
  37.     {  
  38.         switch (item.getItemId())  
  39.         {  
  40.         case R.id.id_action_clip:  
  41.             Bitmap bitmap = mClipImageLayout.clip();  
  42.               
  43.             ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  44.             bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);  
  45.             byte[] datas = baos.toByteArray();  
  46.               
  47.             Intent intent = new Intent(this, ShowImageActivity.class);  
  48.             intent.putExtra("bitmap", datas);  
  49.             startActivity(intent);  
  50.   
  51.             break;  
  52.         }  
  53.         return super.onOptionsItemSelected(item);  
  54.     }  
  55. }  

我们在menu里面体检了一个裁切的按钮,点击后把裁切好的图片传递给我们的ShowImageActivity

看一下眼menu的xml

[html] view plain copy
  1. <menu xmlns:android="http://schemas.android.com/apk/res/android" >  
  2.   
  3.     <item  
  4.         android:id="@+id/id_action_clip"  
  5.         android:icon="@drawable/actionbar_clip_icon"  
  6.         android:showAsAction="always|withText"  
  7.         android:title="裁切"/>  
  8.   
  9. </menu>  

3、ShowImageActivity

[java] view plain copy
  1. package com.zhy.clippic;  
  2.   
  3.   
  4. import android.app.Activity;  
  5. import android.graphics.Bitmap;  
  6. import android.graphics.BitmapFactory;  
  7. import android.os.Bundle;  
  8. import android.widget.ImageView;  
  9.   
  10.   
  11. public class ShowImageActivity extends Activity  
  12. {  
  13.     private ImageView mImageView;  
  14.   
  15.   
  16.     @Override  
  17.     protected void onCreate(Bundle savedInstanceState)  
  18.     {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.show);  
  21.   
  22.   
  23.         mImageView = (ImageView) findViewById(R.id.id_showImage);  
  24.         byte[] b = getIntent().getByteArrayExtra("bitmap");  
  25.         Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);  
  26.         if (bitmap != null)  
  27.         {  
  28.             mImageView.setImageBitmap(bitmap);  
  29.         }  
  30.     }  
  31. }  


layout/show.xml
[html] view plain copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="#ffffff" >  
  6.   
  7.     <ImageView  
  8.         android:id="@+id/id_showImage"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:layout_centerInParent="true"  
  12.         android:src="@drawable/tbug"  
  13.          />  
  14.   
  15. </RelativeLayout>  


好了,到此我们的 高仿微信头像截取功能 就已经结束了~~希望大家可以从本篇博客中可以领悟到something~


最后我们把ClipImageLayout里面的mHorizontalPadding设置为50,贴个静态效果图~



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 植过发15天手抓植发区了怎么办 洗头梳头老掉头发怎么办 掉头发特别特别严重怎么办 哺乳期掉头发特别严重怎么办 最近掉头发特别严重怎么办 近掉头发特别严重怎么办 50多岁脱发严重怎么办 2岁宝宝掉发严重怎么办 生孩子后掉头发严重怎么办 有16岁孩孑教吾听怎么办 生完孩子后脱发怎么办 学生掉头发很厉害怎么办 35岁开始掉头发怎么办 高三学生玩手机怎么办 高三学生不学习怎么办 17岁经常掉头发怎么办 出汗后头皮很痒怎么办 头发老是掉怎么办会不会长出来 头发痒还掉头发怎么办 7个月宝宝入睡难怎么办 45天宝宝入睡难怎么办 两岁宝宝入睡难怎么办 吃激素掉发严重怎么办 20多岁掉头发怎么办 最近头发老掉怎么办20 20多岁最近严重脱发怎么办 头痒头皮屑多掉头发怎么办 有头屑头痒掉头发怎么办 老是头痒掉头发怎么办 头屑头痒掉头发怎么办 头痒头屑多掉头发怎么办 洗头发时总是掉发怎么办 染头发染到脸上洗不掉怎么办 总爱掉头发怎么办20岁 头发开叉长的慢怎么办 洗头时掉很多头发怎么办 出门前头发很油怎么办 关于头发头顶头发少怎么办 每天掉100根头发怎么办 小孩嘴巴烂了该怎么办 小孩吃烧烤嘴巴肿好大该怎么办