Android NineGridLayout — 仿微信朋友圈和QQ空间的九宫格图片展示自定义控件

NineGridLayout

一个仿微信朋友圈和QQ空间的九宫格图片展示自定义控件。

一、介绍

    1、当只有1张图时,可以自己定制图片宽高,也可以使用默认九宫格的宽高;

2、当只有4张图时,以2*2的方式显示;<br/>
3、除以上两种情况下,都是按照3列方式显示,但这时有一些细节:<br/>
    a、如果只有9张图,当然是以3*3的方式显示;<br/>
    b、如果超过9张图,可以设置是否全部显示。<br/>
        如果设置不完全显示,则按照3*3的方式显示,但是在第9张图上会有一个带“+”号的数字,<br/>
        代表还有几张没有显示,这里是模仿了QQ空间图片超出9张的显示方式;<br/>
        如果设置全部显示,理所当然的将所有图片都显示出来。<br/>
4、图片被按下时,会有一个变暗的效果,这也是模仿微信朋友圈的效果。<br/>

二、使用方法

1、核心类是NineGridLayout,继承自ViewGroup的抽象类,所以我们实际项目使用需要继承它,并要实现3个方法,如下:

public abstract class NineGridLayout extends ViewGroup {

//******************************其他代码省略**************************

/**

     * 显示一张图片<br/>
     * @param imageView<br/>
     * @param url<br/>
     * @param parentWidth 父控件宽度<br/>
     * @return true 代表按照九宫格默认大小显示,false 代表按照自定义宽高显示<br/>
     */<br/>
    protected abstract boolean displayOneImage(RatioImageView imageView, String url, int parentWidth);

protected abstract void displayImage(RatioImageView imageView, String url); /**

     * 点击图片时执行<br/>
     */<br/>
    protected abstract void onClickImage(int position, String url, List&lt;String&gt; urlList);<br/>
}</pre>

2、我这里用NineGridTestLayout继承NineGridLayout实现,displayOneImage()与displayImage()中的参数都是显示图片需要的,我这里用的是ImageLoader显示图片,当然你也可以用其他的。

public class NineGridTestLayout extends NineGridLayout {
protected static final int MAX_W_H_RATIO = ;
public NineGridTestLayout(Context context) {

     super(context);<br/>
 }

public NineGridTestLayout(Context context, AttributeSet attrs) {

     super(context, attrs);<br/>
 }

@Override

 protected boolean displayOneImage(final RatioImageView imageView, String url, final int parentWidth) {

//这里是只显示一张图片的情况,显示图片的宽高可以根据实际图片大小自由定制,parentWidth 为该layout的宽度

     ImageLoader.getInstance().displayImage(imageView, url, ImageLoaderUtil.getPhotoImageOption(), new ImageLoadingListener() {<br/>
         @Override<br/>
         public void onLoadingStarted(String imageUri, View view) {

} @Override

         public void onLoadingFailed(String imageUri, View view, FailReason failReason) {

} @Override

         public void onLoadingComplete(String imageUri, View view, Bitmap bitmap) {<br/>
             int w = bitmap.getWidth();<br/>
             int h = bitmap.getHeight();

int newW;

             int newH;<br/>
             if (h &gt; w * MAX_W_H_RATIO) {//h:w = 5:3<br/>
                 newW = parentWidth / ;<br/>
                 newH = newW *  / ;<br/>
             } else if (h &lt; w) {//h:w = 2:3<br/>
                 newW = parentWidth *  / ;<br/>
                 newH = newW *  / ;<br/>
             } else {//newH:h = newW :w<br/>
                 newW = parentWidth / ;<br/>
                 newH = h * newW / w;<br/>
             }<br/>
             setOneImageLayoutParams(imageView, newW, newH);<br/>
         }

@Override

         public void onLoadingCancelled(String imageUri, View view) {

}

     });<br/>
     return false;// true 代表按照九宫格默认大小显示(此时不要调用setOneImageLayoutParams);false 代表按照自定义宽高显示。<br/>
 }

@Override

 protected void displayImage(RatioImageView imageView, String url) {<br/>
     ImageLoaderUtil.getImageLoader(mContext).displayImage(url, imageView, ImageLoaderUtil.getPhotoImageOption());<br/>
 }

@Override

 protected void onClickImage(int i, String url, List&lt;String&gt; urlList) {<br/>
     Toast.makeText(mContext, &#34;点击了图片&#34; + url, Toast.LENGTH_SHORT).show();<br/>
 }<br/>

}

3、在xml中实现

&lt;com.hmy.ninegridlayout.view.NineGridTestLayout xmlns:app=“http://schemas.android.com/apk/res-auto&#34;

android:id=&#34;@+id/layout_nine_grid&#34;<br/>
android:layout_width=&#34;match_parent&#34;<br/>
android:layout_height=&#34;wrap_content&#34;<br/>
android:layout_marginTop=&#34;8dp&#34;<br/>
app:sapcing=&#34;4dp&#34; /&gt;</pre>

app:sapcing是设置九宫格中图片之间的间隔。

4、使用:

    public List&lt;String&gt; urlList = new ArrayList&lt;&gt;();//图片url

NineGridTestLayout layout = (NineGridTestLayout) view.findViewById(R.id.layout_nine_grid);<br/>
layout.setIsShowAll(false); //当传入的图片数超过9张时,是否全部显示<br/>
layout.setSpacing(); //动态设置图片之间的间隔<br/>
layout.setUrlList(urlList); //最后再设置图片url</pre>

三、核心类

NineGridLayout.java

RatioImageView.Java

该类有两个功能:

1、是用于ImageView被按下时有变暗效果

2、ImageView的宽高根据设置的比例动态适配高度,如在xml中设置 app:ratio=”2“ ,ImageView的高度根据其宽度改变,但始终是宽的2倍,该功能在该项目中没有使用。

/**

  • 根据宽高比例自动计算高度ImageView
  • Created by HMY on 2016/4/21.
    */
    public class RatioImageView extends ImageView { /**
    • 宽高比例
      */
      private float mRatio = 0f; public RatioImageView(Context context, AttributeSet attrs, int defStyleAttr) {
      super(context, attrs, defStyleAttr);
      } public RatioImageView(Context context, AttributeSet attrs) {
      super(context, attrs);
      TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatioImageView); mRatio = typedArray.getFloat(R.styleable.RatioImageView_ratio, 0f);
      typedArray.recycle();
      } public RatioImageView(Context context) {
      super(context);
      } /**
    • 设置ImageView的宽高比
      *
    • @param ratio
      */
      public void setRatio(float ratio) {
      mRatio = ratio;
      } @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      int width = MeasureSpec.getSize(widthMeasureSpec);
      if (mRatio != ) {
      float height = width / mRatio;
      heightMeasureSpec = MeasureSpec.makeMeasureSpec((int) height, MeasureSpec.EXACTLY);
      }
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      } @Override
      public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
      Drawable drawable = getDrawable();
      if (drawable != null) {
      drawable.mutate().setColorFilter(Color.GRAY,
      PorterDuff.Mode.MULTIPLY);
      }
      break;
      case MotionEvent.ACTION_MOVE:
      break;
      case MotionEvent.ACTION_CANCEL:
      case MotionEvent.ACTION_UP:
      Drawable drawableUp = getDrawable();
      if (drawableUp != null) {
      drawableUp.mutate().clearColorFilter();
      }
      break;
      } return super.onTouchEvent(event);
      } }

代码可在我的GitHub上下载,地址:https://github.com/HMY314/NineGridLayout

效果图