• 类似微信朋友圈,点击+号图片,可以加图片


    xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="40dp"
    android:orientation="vertical" >
    
    <com.sw.demo.widget.NinePhotoView
        android:id="@+id/photoview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:ninephoto_hspace="10dp"
        app:ninephoto_vspace="10dp"
        app:rainbowbar_color="@android:color/holo_blue_bright" >
    
    </com.sw.demo.widget.NinePhotoView>
    

    NinePhotoView.java

    public class NinePhotoView extends ViewGroup {
    
    public static final int MAX_PHOTO_NUMBER = 9;
    
    private int[] constImageIds = { R.drawable.girl_0, R.drawable.girl_1,
          R.drawable.girl_2, R.drawable.girl_3, R.drawable.girl_4,
          R.drawable.girl_5, R.drawable.girl_6, R.drawable.girl_7,
          R.drawable.girl_8 };
    
    // horizontal space among children views
    int hSpace = Utils.dpToPx(10, getResources());
    // vertical space among children views
    int vSpace = Utils.dpToPx(10, getResources());
    
    // every child view width and height.
    int childWidth = 0;
    int childHeight = 0;
    
    // store images res id
    ArrayList<integer> mImageResArrayList = new ArrayList<integer>(9);
    private View addPhotoView;
    
    public NinePhotoView(Context context) {
      super(context);
    }
    
    public NinePhotoView(Context context, AttributeSet attrs) {
      this(context, attrs, 0);
    }
    
    public NinePhotoView(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
    
      TypedArray t = context.obtainStyledAttributes(attrs,
              R.styleable.NinePhotoView, 0, 0);
      hSpace = t.getDimensionPixelSize(
              R.styleable.NinePhotoView_ninephoto_hspace, hSpace);
      vSpace = t.getDimensionPixelSize(
              R.styleable.NinePhotoView_ninephoto_vspace, vSpace);
      t.recycle();
    
      addPhotoView = new View(context);
      addView(addPhotoView);
      mImageResArrayList.add(new integer());
    }
    

    Measure

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      int rw = MeasureSpec.getSize(widthMeasureSpec);
      int rh = MeasureSpec.getSize(heightMeasureSpec);
    
      childWidth = (rw - 2 * hSpace) / 3;
      childHeight = childWidth;
    
      int childCount = this.getChildCount();
      for (int i = 0; i < childCount; i++) {
          View child = this.getChildAt(i);
          //this.measureChild(child, widthMeasureSpec, heightMeasureSpec);
    
          LayoutParams lParams = (LayoutParams) child.getLayoutParams();
          lParams.left = (i % 3) * (childWidth + hSpace);
          lParams.top = (i / 3) * (childWidth + vSpace);
      }
    
      int vw = rw;
      int vh = rh;
      if (childCount < 3) {
          vw = childCount * (childWidth + hSpace);
      }
      vh = ((childCount + 3) / 3) * (childWidth + vSpace);
      setMeasuredDimension(vw, vh);
    }
    

      我们的子View三个一排,而且都是正方形,所以我们上面通过循环很好去得到所有子View的位置,注意我们上面把子View的左上角坐标存储到我们自定义的LayoutParams 的left和top二个字段中,Layout阶段会使用,最后我们算得整个ViewGroup的宽高,调用setMeasuredDimension设置。  

     

    Layout

    @Override
    protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
      int childCount = this.getChildCount();
      for (int i = 0; i < childCount; i++) {
          View child = this.getChildAt(i);
          LayoutParams lParams = (LayoutParams) child.getLayoutParams();
          child.layout(lParams.left, lParams.top, lParams.left + childWidth,
                  lParams.top + childHeight);
    
          if (i == mImageResArrayList.size() - 1 && mImageResArrayList.size() != MAX_PHOTO_NUMBER) {
              child.setBackgroundResource(R.drawable.add_photo);
              child.setOnClickListener(new View.OnClickListener() {
    
                  @Override
                  public void onClick(View arg0) {
                      addPhotoBtnClick();
                  }
              });
          }else {
              child.setBackgroundResource(constImageIds[i]);
              child.setOnClickListener(null);
          }
      }
    }
    
    public void addPhoto() {
      if (mImageResArrayList.size() < MAX_PHOTO_NUMBER) {
          View newChild = new View(getContext());
          addView(newChild);
          mImageResArrayList.add(new integer());
          requestLayout();
          invalidate();
      }
    }
    
    public void addPhotoBtnClick() {
      final CharSequence[] items = { "Take Photo", "Photo from gallery" };
    
      AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
      builder.setItems(items, new DialogInterface.OnClickListener() {
    
          @Override
          public void onClick(DialogInterface arg0, int arg1) {
              addPhoto();
          }
    
      });
      builder.show();
    }
    

      最核心的就是调用layout方法,根据我们measure阶段获得的LayoutParams中的left和top字段,也很好对每个子View进行位置排列。然后判断在图片未达到最大值9张时,默认最后一张是+号图片,然后设置点击事件,弹出对话框供用户选择操作。

    Draw
    不需要重写,使用ViewGroup默认实现即可。

     

      

    NiewPhotoView.gif
     
     
  • 相关阅读:
    socket编程技巧(2)发送缓冲区和接收缓冲区的设置时机
    socket编程技巧(1)tcp接收接口(变长数据定长数据)的编写实例
    libnet介绍与分析
    TCP的6大标示符号
    数据帧中常见协议类型
    C语言中offsetof宏的应用
    ip欺骗(原始套接字系列九)
    ARP欺骗(原始套接字系列八)
    包分析(原始套接字七)
    了解Javascript中函数作为对象的魅力
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/6706675.html
Copyright © 2020-2023  润新知