使用了android 2.0以上的ExifInterface来生成缩略图。可用来设计游戏的选关界面。
import uk.co.jasonfry.android.tools.ui.PageControl.OnPageControlClickListener; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.Display; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; public class SwipeView extends HorizontalScrollView { private static int DEFAULT_SWIPE_THRESHOLD = 60; private LinearLayout mLinearLayout; private Context mContext; private int SCREEN_WIDTH; private int mMotionStartX; private int mMotionStartY; private boolean mMostlyScrollingInX = false; private boolean mMostlyScrollingInY = false; private boolean mJustInterceptedAndIgnored = false; protected boolean mCallScrollToPageInOnLayout = false; private int mCurrentPage = 0; private int mPageWidth = 0; private OnPageChangedListener mOnPageChangedListener = null; private SwipeOnTouchListener mSwipeOnTouchListener; private View.OnTouchListener mOnTouchListener; private PageControl mPageControl = null; /** * {@inheritDoc} */ public SwipeView(Context context) { super(context); mContext = context; initSwipeView(); } /** * {@inheritDoc} */ public SwipeView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; initSwipeView(); } /** * {@inheritDoc} */ public SwipeView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs,defStyle); mContext = context; initSwipeView(); } private void initSwipeView() { Log.i("uk.co.jasonfry.android.tools.ui.SwipeView","Initialising SwipeView"); mLinearLayout = new LinearLayout(mContext); mLinearLayout.setOrientation(LinearLayout.HORIZONTAL); super.addView(mLinearLayout, -1, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); setSmoothScrollingEnabled(true); setHorizontalFadingEdgeEnabled(false); setHorizontalScrollBarEnabled(false); Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); SCREEN_WIDTH = (int) (display.getWidth()); mPageWidth = SCREEN_WIDTH; mCurrentPage = 0; mSwipeOnTouchListener = new SwipeOnTouchListener(); super.setOnTouchListener(mSwipeOnTouchListener); } /** * {@inheritDoc} */ @Override public boolean onTrackballEvent(MotionEvent event) { return true; } @Override protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { //this will now pass trackball events down to onTrackballEvent return false; } @Override public void requestChildFocus(View child, View focused) { //this will now pass trackball events down to onRequestFocusInDescendants requestFocus(); } /** * {@inheritDoc} */ @Override public void addView(View child) { this.addView(child,-1); } /** * {@inheritDoc} */ @Override public void addView (View child, int index) { ViewGroup.LayoutParams params; if(child.getLayoutParams()==null) { params = new LayoutParams(mPageWidth, LayoutParams.FILL_PARENT); } else { params = child.getLayoutParams(); params.width = mPageWidth; } this.addView(child, index, params); } /** * {@inheritDoc} */ @Override public void addView (View child, ViewGroup.LayoutParams params) { params.width = mPageWidth; this.addView (child, -1, params); } /** * {@inheritDoc} */ @Override public void addView (View child, int index, ViewGroup.LayoutParams params) { requestLayout(); invalidate(); mLinearLayout.addView(child, index, params); } /** * {@inheritDoc} */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if(mCallScrollToPageInOnLayout) { scrollToPage(mCurrentPage); mCallScrollToPageInOnLayout = false; } } /** * {@inheritDoc} */ @Override public void setOnTouchListener(View.OnTouchListener onTouchListener) { mOnTouchListener = onTouchListener; } /** * Get the View object that contains all the children of this SwipeView. The same as calling getChildAt(0) * A SwipeView behaves slightly differently from a normal ViewGroup, all the children of a SwipeView * sit within a LinearLayout, which then sits within the SwipeView object. * * @return linearLayout The View object that contains all the children of this view */ public LinearLayout getChildContainer() { return mLinearLayout; } /** * Get the swiping threshold distance to make the screens change * * @return swipeThreshold The minimum distance the finger should move to allow the screens to change */ public int getSwipeThreshold() { return DEFAULT_SWIPE_THRESHOLD; } /** * Set the swiping threshold distance to make the screens change * * @param swipeThreshold The minimum distance the finger should move to allow the screens to change */ public void setSwipeThreshold(int swipeThreshold) { DEFAULT_SWIPE_THRESHOLD = swipeThreshold; } /** * Get the current page the SwipeView is on * * @return The current page the SwipeView is on */ public int getCurrentPage() { return mCurrentPage; } /** * Return the number of pages in this SwipeView * * @return Returns the number of pages in this SwipeView */ public int getPageCount() { return mLinearLayout.getChildCount(); } /** * Go directly to the specified page * * @param page The page to scroll to */ public void scrollToPage(int page) { scrollToPage(page,false); } /** * Animate a scroll to the specified page * * @param page The page to animate to */ public void smoothScrollToPage(int page) { scrollToPage(page,true); } private void scrollToPage(int page, boolean smooth) { int oldPage = mCurrentPage; if(page>=getPageCount() && getPageCount()>0) { page--; } else if(page<0) { page=0; } if(smooth) { smoothScrollTo(page*mPageWidth,0); } else { scrollTo(page*mPageWidth,0); } mCurrentPage = page; if(mOnPageChangedListener!=null && oldPage!=page) { mOnPageChangedListener.onPageChanged(oldPage, page); } if(mPageControl!=null && oldPage!=page) { mPageControl.setCurrentPage(page); } mCallScrollToPageInOnLayout=!mCallScrollToPageInOnLayout; } /** * Set the width of each page. This function returns an integer that should be added to the left margin of * the first child and the right margin of the last child. This enables all the children to appear to be * central * * @param pageWidth The width you wish to assign for each page * @return An integer to add to the left margin of the first child and the right margin of the last child */ public int setPageWidth(int pageWidth) { mPageWidth = pageWidth; return (SCREEN_WIDTH - mPageWidth)/2; } /** * Set the width of each page by using the layout parameters of a child. Call this function before you add * the child to the SwipeView to maintain the child's size. This function returns an integer that should * be added to the left margin of the first child and the right margin of the last child. This enables all * the children to appear to be central * * @param childLayoutParams A child view that you have added / will add to the SwipeView * @return An integer to add to the left margin of the first child and the right margin of the last child */ public int calculatePageSize(MarginLayoutParams childLayoutParams) { return setPageWidth(childLayoutParams.leftMargin + childLayoutParams.width + childLayoutParams.rightMargin); } /** * Return the current width of each page * * @return Returns the width of each page */ public int getPageWidth() { return mPageWidth; } /** * Assign a PageControl object to this SwipeView. Call after adding all the children * * @param pageControl The PageControl object to assign */ public void setPageControl(PageControl pageControl) { mPageControl = pageControl; pageControl.setPageCount(getPageCount()); pageControl.setCurrentPage(mCurrentPage); pageControl.setOnPageControlClickListener(new OnPageControlClickListener() { public void goForwards() { smoothScrollToPage(mCurrentPage+1); } public void goBackwards() { smoothScrollToPage(mCurrentPage-1); } }); } /** * Return the current PageControl object * * @return Returns the current PageControl object */ public PageControl getPageControl() { return mPageControl; } /** * Implement this listener to listen for page change events * * @author Jason Fry - jasonfry.co.uk * */ public interface OnPageChangedListener { /** * Event for when a page changes * * @param oldPage The page the view was on previously * @param newPage The page the view has moved to */ public abstract void onPageChanged(int oldPage, int newPage); } /** * Set the current OnPageChangedListsner * * @param onPageChangedListener The OnPageChangedListener object */ public void setOnPageChangedListener(OnPageChangedListener onPageChangedListener) { mOnPageChangedListener = onPageChangedListener; } /** * Get the current OnPageChangeListsner * * @return The current OnPageChangedListener */ public OnPageChangedListener getOnPageChangedListener() { return mOnPageChangedListener; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { boolean result = super.onInterceptTouchEvent(ev); if(ev.getAction() == MotionEvent.ACTION_DOWN) { mMotionStartX = (int) ev.getX(); mMotionStartY = (int) ev.getY(); if(!mJustInterceptedAndIgnored) { mMostlyScrollingInX = false; mMostlyScrollingInY = false; } } else if(ev.getAction()==MotionEvent.ACTION_MOVE) { detectMostlyScrollingDirection(ev); } if(mMostlyScrollingInY) { return false; } if(mMostlyScrollingInX) { mJustInterceptedAndIgnored = true; return true; } return result; } private void detectMostlyScrollingDirection(MotionEvent ev) { if(!mMostlyScrollingInX && !mMostlyScrollingInY) //if we dont know which direction we're going yet { float xDistance = Math.abs(mMotionStartX - ev.getX()); float yDistance = Math.abs(mMotionStartY - ev.getY()); if(yDistance>xDistance+5) { mMostlyScrollingInY = true; } else if(xDistance>yDistance+5) { mMostlyScrollingInX = true; } } } private class SwipeOnTouchListener implements View.OnTouchListener { private boolean mSendingDummyMotionEvent = false; private int mDistanceX; private int mPreviousDirection; private boolean mFirstMotionEvent = true; public boolean onTouch(View v, MotionEvent event) { if(mOnTouchListener!=null && !mJustInterceptedAndIgnored || mOnTouchListener!=null && mSendingDummyMotionEvent) //send on touch event to onTouchListener set by an application implementing a SwipeView and setting their own onTouchListener { if(mOnTouchListener.onTouch(v, event)) { if(event.getAction() == MotionEvent.ACTION_UP) //this comes back if a very quick movement event has happened over a view with an onClick { //need to call the actionUp directly so the view is not left between pages. actionUp(event); } return true; } } if(mSendingDummyMotionEvent)//if sending the fake action down event (to do with vertical scrolling within this horizontalscrollview) then just ignore it { mSendingDummyMotionEvent = false; return false; } switch(event.getAction()) { case MotionEvent.ACTION_DOWN : return actionDown(event); case MotionEvent.ACTION_MOVE : return actionMove(event); case MotionEvent.ACTION_UP : return actionUp(event); } return false; } private boolean actionDown(MotionEvent event) { mMotionStartX = (int) event.getX(); mMotionStartY = (int) event.getY(); mFirstMotionEvent = false; return false; } private boolean actionMove(MotionEvent event) { int newDistance = mMotionStartX - (int) event.getX(); int newDirection; if(newDistance<0) //backwards { newDirection = (mDistanceX+4 <= newDistance) ? 1 : -1; //the distance +4 is to allow for jitter } else //forwards { newDirection = (mDistanceX-4 <= newDistance) ? 1 : -1; //the distance -4 is to allow for jitter } if(newDirection != mPreviousDirection && !mFirstMotionEvent)//changed direction, so reset start point { mMotionStartX = (int) event.getX(); mDistanceX = mMotionStartX - (int) event.getX(); } else { mDistanceX = newDistance; } mPreviousDirection = newDirection; //backwards -1, forwards is 1, if(mJustInterceptedAndIgnored)//if the intercept picked it up first, we need to give the horizontalscrollview ontouch an action down to enable it to scroll and follow your finger { mSendingDummyMotionEvent = true; dispatchTouchEvent(MotionEvent.obtain(event.getDownTime(), event.getEventTime(), MotionEvent.ACTION_DOWN, mMotionStartX, mMotionStartY, event.getPressure(), event.getSize(), event.getMetaState(), event.getXPrecision(), event.getYPrecision(), event.getDeviceId(), event.getEdgeFlags())); mJustInterceptedAndIgnored = false; return true; } return false; } private boolean actionUp(MotionEvent event) { float fingerUpPosition = getScrollX(); float numberOfPages = mLinearLayout.getMeasuredWidth() / mPageWidth; float fingerUpPage = fingerUpPosition/mPageWidth; float edgePosition = 0; if(mPreviousDirection == 1) //forwards { if(mDistanceX > DEFAULT_SWIPE_THRESHOLD)//if over then go forwards { if(mCurrentPage<(numberOfPages-1))//if not at the end of the pages, you don't want to try and advance into nothing! { edgePosition = (int)(fingerUpPage+1)*mPageWidth; } else { edgePosition = (int)(mCurrentPage)*mPageWidth; } } else //return to start position { if(Math.round(fingerUpPage)==numberOfPages-1)//if at the end { //need to correct for when user starts to scroll into //nothing then pulls it back a bit, this becomes a //kind of forwards scroll instead edgePosition = (int)(fingerUpPage+1)*mPageWidth; } else //carry on as normal { edgePosition = mCurrentPage*mPageWidth; } } } else //backwards { if(mDistanceX < -DEFAULT_SWIPE_THRESHOLD)//go backwards { edgePosition = (int)(fingerUpPage)*mPageWidth; } else //return to start position { if(Math.round(fingerUpPage)==0)//if at beginning, correct { //need to correct for when user starts to scroll into //nothing then pulls it back a bit, this becomes a //kind of backwards scroll instead edgePosition = (int)(fingerUpPage)*mPageWidth; } else //carry on as normal { edgePosition = mCurrentPage*mPageWidth; } } } smoothScrollToPage((int)edgePosition/mPageWidth); mFirstMotionEvent = true; mDistanceX = 0; mMostlyScrollingInX = false; mMostlyScrollingInY = false; return true; } } }
import java.util.ArrayList; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.OvalShape; import android.graphics.drawable.shapes.Shape; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; public class PageControl extends LinearLayout { private int mIndicatorSize = 7; private Drawable activeDrawable; private Drawable inactiveDrawable; private ArrayList<ImageView> indicators; private int mPageCount = 0; private int mCurrentPage = 0; private Context mContext; private OnPageControlClickListener mOnPageControlClickListener = null; public PageControl(Context context) { super(context); mContext = context; initPageControl(); } public PageControl(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; //will now wait until onFinishInflate to call initPageControl() } @Override protected void onFinishInflate() { initPageControl(); } private void initPageControl() { Log.i("uk.co.jasonfry.android.tools.ui.PageControl","Initialising PageControl"); indicators = new ArrayList<ImageView>(); activeDrawable = new ShapeDrawable(); inactiveDrawable = new ShapeDrawable(); activeDrawable.setBounds(0, 0, mIndicatorSize, mIndicatorSize); inactiveDrawable.setBounds(0, 0, mIndicatorSize, mIndicatorSize); Shape s1 = new OvalShape(); s1.resize(mIndicatorSize, mIndicatorSize); Shape s2 = new OvalShape(); s2.resize(mIndicatorSize, mIndicatorSize); int i[] = new int[2]; i[0] = android.R.attr.textColorSecondary; i[1] = android.R.attr.textColorSecondaryInverse; TypedArray a = mContext.getTheme().obtainStyledAttributes(i); ((ShapeDrawable) activeDrawable).getPaint().setColor(a.getColor(0, Color.DKGRAY)); ((ShapeDrawable) inactiveDrawable).getPaint().setColor(a.getColor(1, Color.LTGRAY)); ((ShapeDrawable) activeDrawable).setShape(s1); ((ShapeDrawable) inactiveDrawable).setShape(s2); mIndicatorSize = (int) (mIndicatorSize * getResources().getDisplayMetrics().density); setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if(mOnPageControlClickListener != null) { switch(event.getAction()) { case MotionEvent.ACTION_UP : if(PageControl.this.getOrientation() == LinearLayout.HORIZONTAL) { if(event.getX()<(PageControl.this.getWidth()/2)) //if on left of view { if(mCurrentPage>0) { mOnPageControlClickListener.goBackwards(); } } else //if on right of view { if(mCurrentPage<(mPageCount-1)) { mOnPageControlClickListener.goForwards(); } } } else { if(event.getY()<(PageControl.this.getHeight()/2)) //if on top half of view { if(mCurrentPage>0) { mOnPageControlClickListener.goBackwards(); } } else //if on bottom half of view { if(mCurrentPage<(mPageCount-1)) { mOnPageControlClickListener.goForwards(); } } } return false; } } return true; } }); } /** * Set the drawable object for an active page indicator * * @param d The drawable object for an active page indicator */ public void setActiveDrawable(Drawable d) { activeDrawable = d; indicators.get(mCurrentPage).setBackgroundDrawable(activeDrawable); } /** * Return the current drawable object for an active page indicator * * @return Returns the current drawable object for an active page indicator */ public Drawable getActiveDrawable() { return activeDrawable; } /** * Set the drawable object for an inactive page indicator * * @param d The drawable object for an inactive page indicator */ public void setInactiveDrawable(Drawable d) { inactiveDrawable = d; for(int i=0; i<mPageCount; i++) { indicators.get(i).setBackgroundDrawable(inactiveDrawable); } indicators.get(mCurrentPage).setBackgroundDrawable(activeDrawable); } /** * Return the current drawable object for an inactive page indicator * * @return Returns the current drawable object for an inactive page indicator */ public Drawable getInactiveDrawable() { return inactiveDrawable; } /** * Set the number of pages this PageControl should have * * @param pageCount The number of pages this PageControl should have */ public void setPageCount(int pageCount) { mPageCount = pageCount; for(int i=0;i<pageCount;i++) { final ImageView imageView = new ImageView(mContext); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(mIndicatorSize, mIndicatorSize); params.setMargins(mIndicatorSize/2, mIndicatorSize, mIndicatorSize/2, mIndicatorSize); imageView.setLayoutParams(params); imageView.setBackgroundDrawable(inactiveDrawable); indicators.add(imageView); addView(imageView); } } /** * Return the number of pages this PageControl has * * @return Returns the number of pages this PageControl has */ public int getPageCount() { return mPageCount; } /** * Set the current page the PageControl should be on * * @param currentPage The current page the PageControl should be on */ public void setCurrentPage(int currentPage) { if(currentPage<mPageCount) { indicators.get(mCurrentPage).setBackgroundDrawable(inactiveDrawable);//reset old indicator indicators.get(currentPage).setBackgroundDrawable(activeDrawable);//set up new indicator mCurrentPage = currentPage; } } /** * Return the current page the PageControl is on * * @return Returns the current page the PageControl is on */ public int getCurrentPage() { return mCurrentPage; } /** * Set the size of the page indicator drawables * * @param indicatorSize The size of the page indicator drawables */ public void setIndicatorSize(int indicatorSize) { mIndicatorSize=indicatorSize; for(int i=0;i<mPageCount;i++) { indicators.get(i).setLayoutParams(new LayoutParams(mIndicatorSize, mIndicatorSize)); } } /** * Return the size of the page indicator drawables * * @return Returns the size of the page indicator drawables */ public int getIndicatorSize() { return mIndicatorSize; } /** * * @author Jason Fry - jasonfry.co.uk * * Interface definition for a callback to be invoked when a PageControl is clicked. * */ public interface OnPageControlClickListener { /** * Called when the PageControl should go forwards * */ public abstract void goForwards(); /** * Called when the PageControl should go backwards * */ public abstract void goBackwards(); } /** * Set the OnPageControlClickListener object for this PageControl * * @param onPageControlClickListener The OnPageControlClickListener you wish to set */ public void setOnPageControlClickListener(OnPageControlClickListener onPageControlClickListener) { mOnPageControlClickListener = onPageControlClickListener; } /** * Return the OnPageControlClickListener that has been set on this PageControl * * @return Returns the OnPageControlClickListener that has been set on this PageControl */ public OnPageControlClickListener getOnPageControlClickListener() { return mOnPageControlClickListener; } }