自定义控件实现图片布局

在开发过程中需要做一个相册遇到 一个问题。需要对图片进行布局;当时效果图是自定义控件实现图片布局_第1张图片

当时我使用的是一个固定布局和一个gridview结合起来做成的。。现在使用自定义groupview将这个效果实现

效果图如下:

自定义控件实现图片布局_第2张图片


接下来到了自定义groupview的时候啦

package com.ww.mypicture;

import java.util.ArrayList;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Scroller;

public class MyPhotoView extends ViewGroup implements OnGestureListener{
	private int driverDP=0;
	private int imageWidth;
	private int currentWidth=0;
	private int currentHeight=0;
	private ArrayList<String> url=new ArrayList<>();
	private int width;
	private float mLastMotionY;// 最后点击的点  
    private GestureDetector detector;  
    int move = 0;// 移动距离  
    int MAXMOVE = 850;// 最大允许的移动距离  
    private Scroller mScroller;  
    int up_excess_move = 0;// 往上多移的距离  
    int down_excess_move = 0;// 往下多移的距离  
    private final static int TOUCH_STATE_REST = 0;  
    private final static int TOUCH_STATE_SCROLLING = 1;  
    private int mTouchSlop;  
    private int mTouchState = TOUCH_STATE_REST;
	public MyPhotoView(Context context, AttributeSet attrs) {
		super(context, attrs);
		mScroller = new Scroller(context);  
        detector = new GestureDetector(this);  
        final ViewConfiguration configuration = ViewConfiguration.get(context);  
        // 获得可以认为是滚动的距离  
        mTouchSlop = configuration.getScaledTouchSlop(); 
		/*WindowManager dmManager=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		DisplayMetrics dmDisplayMetrics=new DisplayMetrics();
		dmManager.getDefaultDisplay().getMetrics(dmDisplayMetrics);
		Swidth=dmDisplayMetrics.widthPixels;*/
		TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.MyPhotoView);
		driverDP= (int) array.getDimension(R.styleable.MyPhotoView_driverDP, 0);
		array.recycle();
	}
	
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// TODO Auto-generated method stub
		if (changed) {
			imageWidth=(getMeasuredWidth()-driverDP*2-getPaddingLeft()-getPaddingRight())/3;
			int count =getChildCount();
			for (int i = 0; i < url.size(); i++) {
				getCurrentSize(i);
				if (i==0) {
					width=imageWidth*2+driverDP;
				}else {
					width=imageWidth;
				}
				View child=getChildAt(i);
				LinearLayout.LayoutParams lParams;
				lParams=new LinearLayout.
						LayoutParams(width, width);
				child.setLayoutParams(lParams);
				child.layout(currentWidth, currentHeight, currentWidth+width, currentHeight+width);
			}
		}
	}
	 @Override  
	    public void computeScroll() {  
	        if (mScroller.computeScrollOffset()) {  
	            // 返回当前滚动X方向的偏移  
	            scrollTo(0, mScroller.getCurrY());  
	            postInvalidate();  
	        }  
	    } 
	 @Override  
	    public boolean onInterceptTouchEvent(MotionEvent ev) {  
	        final int action = ev.getAction();  
	  
	        final float y = ev.getY();  
	        switch (ev.getAction())  
	        {  
	        case MotionEvent.ACTION_DOWN:  
	  
	            mLastMotionY = y;  
	            mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST  
	                    : TOUCH_STATE_SCROLLING;  
	            break;  
	        case MotionEvent.ACTION_MOVE:  
	            final int yDiff = (int) Math.abs(y - mLastMotionY);  
	            boolean yMoved = yDiff > mTouchSlop;  
	            // 判断是否是移动  
	            if (yMoved) {  
	                mTouchState = TOUCH_STATE_SCROLLING;  
	            }  
	            break;  
	        case MotionEvent.ACTION_UP:  
	            mTouchState = TOUCH_STATE_REST;  
	            break;  
	        }  
	        return mTouchState != TOUCH_STATE_REST;  
	    }
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		MAXMOVE=(url.size()/3+url.size()%3==0?0:1+2)*(imageWidth+driverDP)-driverDP;  
        final float y = ev.getY();  
        switch (ev.getAction())  
        {  
        case MotionEvent.ACTION_DOWN:  
            if (!mScroller.isFinished()) {  
                mScroller.forceFinished(true);  
                move = mScroller.getFinalY();  
            }  
            mLastMotionY = y;  
            break;  
        case MotionEvent.ACTION_MOVE:  
            if (ev.getPointerCount() == 1) {  
                  
                // 随手指 拖动的代码  
                int deltaY = 0;  
                deltaY = (int) (mLastMotionY - y);  
                mLastMotionY = y;  
                if (deltaY < 0) {  
                    // 下移  
                    // 判断上移 是否滑过头  
                    if (up_excess_move == 0) {  
                        if (move > 0) {  
                            int move_this = Math.max(-move, deltaY);  
                            move = move + move_this;  
                            scrollBy(0, move_this);  
                        } else if (move == 0) {// 如果已经是最顶端 继续往下拉  
                            down_excess_move = down_excess_move - deltaY / 2;// 记录下多往下拉的值  
                            scrollBy(0, deltaY / 2);  
                        }  
                    } else if (up_excess_move > 0)// 之前有上移过头  
                    {                     
                        if (up_excess_move >= (-deltaY)) {  
                            up_excess_move = up_excess_move + deltaY;  
                            scrollBy(0, deltaY);  
                        } else {                          
                            up_excess_move = 0;  
                            scrollBy(0, -up_excess_move);                 
                        }  
                    }  
                } else if (deltaY > 0) {  
                    // 上移  
                    if (down_excess_move == 0) {  
                        if (MAXMOVE - move > 0) {  
                            int move_this = Math.min(MAXMOVE - move, deltaY);  
                            move = move + move_this;  
                            scrollBy(0, move_this);  
                        } else if (MAXMOVE - move == 0) {  
                            if (up_excess_move <= 100) {  
                                up_excess_move = up_excess_move + deltaY / 2;  
                                scrollBy(0, deltaY / 2);  
                            }  
                        }  
                    } else if (down_excess_move > 0) {  
                        if (down_excess_move >= deltaY) {  
                            down_excess_move = down_excess_move - deltaY;  
                            scrollBy(0, deltaY);  
                        } else {  
                            down_excess_move = 0;  
                            scrollBy(0, down_excess_move);  
                        }  
                    }  
                }         
            }   
            break;  
        case MotionEvent.ACTION_UP:           
            // 多滚是负数 记录到move里  
            if (up_excess_move > 0) {  
                // 多滚了 要弹回去  
                scrollBy(0, -up_excess_move);  
                invalidate();  
                up_excess_move = 0;  
            }  
            if (down_excess_move > 0) {  
                // 多滚了 要弹回去  
                scrollBy(0, down_excess_move);  
                invalidate();  
                down_excess_move = 0;  
            }  
            mTouchState = TOUCH_STATE_REST;  
            break;  
        }  
        return this.detector.onTouchEvent(ev); 
	}
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		for(int i=0;i<url.size();i++){
//			MyImageView imageView=new MyImageView(getContext());
			ImageView imageView=new ImageView(getContext());
//			imageView.setImage(R.drawable.ic_launcher);
			imageView.setImageDrawable(getContext().getResources().getDrawable(R.drawable.img_sex_boy_pressed));
			imageView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
			addView(imageView,i);
		}
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		
	}
	private void getCurrentSize(int i){
		if (i<3) {
			if (i==0) {
				currentWidth=getPaddingLeft();
			}else {
				currentWidth=getPaddingLeft()+(imageWidth+driverDP)*2;
			}
			if (i==2) {
				currentHeight=imageWidth+driverDP+getPaddingTop();
			}else {
				currentHeight=getPaddingTop();
			}
		}else {
			currentWidth=i%3*(imageWidth+driverDP)+getPaddingLeft();
			currentHeight=(i/3+1)*(imageWidth+driverDP)+getPaddingTop();
		}
	}
	public void setUrl(ArrayList<String> urlString){
		url.clear();
		if (urlString!=null) {
			url.addAll(urlString);
		}
	}
	public void addUrl(ArrayList<String> urlString){
		if (urlString!=null) {
			url.addAll(urlString);
		}
	}
	public void setDriverDP(int dp){
		this.driverDP=dp;
	}

	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		return true;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub
		
	}
	 int Fling_move = 0; 
	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		if (up_excess_move == 0 && down_excess_move == 0) {  
			  
            int slow = -(int) velocityY * 3 / 4;  
            mScroller.fling(0, move, 0, slow, 0, 0, 0, MAXMOVE);  
            move = mScroller.getFinalY();  
            computeScroll();  
        }  
		return false;
	}
}
其中自定义控件和布局是在onMeasur()和onLayout()方法中。。实现滑动效果是对事件进行重写(此处是借鉴度娘上的代码)关于此处本人还有待学习。。

由于只是测试demo所以还有很多地方需要完善,,,比方说点击效果分页等等。。

其他的布局使用和逻辑控制代码都比较简单。。所以就不多说了。。。



你可能感兴趣的:(自定义控件实现图片布局)