项目GitHub地址https://github.com/tikeyc/TNinePlaceGridView_Android https://github.com/tikeyc/TikeycAndroid
玩Android不久,根据iOS实现思路https://github.com/tikeyc/TNinePlaceGridView
封装了一个。详情见TNinePlaceGridView
说说我的实现思路:
逐渐掌握了Android开发套路,是时候自己去封装一些东西了。网上看了一些例子,感觉不是我想要的那种,我希望是直接导入就用,没有Activity,没有xml布局文件,全代码创建那种,使用者用起来直接用到一个类或者两个类就OK的那种。故此花了一点时间封装了这么一个九宫格:
需要有这么一个控件,这个控件是一个图片控件TScallImageView,点击这个图片会从图片位置开始放大至全屏TImageListBgView,点击后全屏缩小到原来位置,且放大缩小过程背景透明可以看见当前UI界面;这个全屏大部分人可能是start一个Activity(这样的话还得再功能清单文件添加该Activity,这不是我想要的),这里我直接添加到了window上;这些代码逻辑主要都写在TImageListBgView类中。
这里需要获取图片相对于window的位置:这里自定义了一个记录位置信息的类TRect
package com.tikeyc.tikeycandroid.custom.TNinePlaceGridView; /** * Created by public1 on 2017/5/23. */ public class TRect { private int left; private int top; private int width; private int height; public TRect(int left, int top, int width, int height) { this.left = left; this.top = top; this.width = width; this.height = height; } public int getLeft() { return left; } public int getTop() { return top; } public int getWidth() { return width; } public int getHeight() { return height; } public void setLeft(int left) { this.left = left; } public void setTop(int top) { this.top = top; } public void setWidth(int width) { this.width = width; } public void setHeight(int height) { this.height = height; } @Override public String toString() { return "TRect{" + "left=" + left + ", top=" + top + ", width=" + width + ", height=" + height + '}'; } }
图片控件:TScallImageView
- 该控件可以xml中创建也可代码创建,不过在调用其showImageToWindow()方法之前,需设置一下几个属性值:其中imageId及imageIds可以是图片URL也可以是图片id值。
public ViewGroup ninePlaceGridView;//外部设置 public Object imageId;//外部设置 public List<Object> imageIds;//外部设置 public int currentIndex;//外部设置
package com.tikeyc.tnineplacegridviewlibrary.TNinePlaceGridView; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; /** * Created by public1 on 2017/5/19. */ public class TScallImageView extends android.support.v7.widget.AppCompatImageView { public static final int STATE_NORMAL = 0; public static final int STATE_TRANSFORM_IN = 1; public static final int STATE_TRANSFORM_OUT = 2; public ViewGroup ninePlaceGridView;//外部设置 private TRect originalRect;//得到的第一个图片相对于window的位置 private List<TRect> originalRects;//得到的第所有图片相对于window的位置 public Object imageId;//外部设置 public List<Object> imageIds;//外部设置 public int currentIndex;//外部设置 public TImageListBgView imageListBgView; public TScallImageView(Context context) { super(context); init(); } public TScallImageView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public TScallImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { showImageToWindow(); } }); } /**获取每个图片相对于window的位置 * @return */ private List<TRect> getOriginalRects() { List<TRect> originalRects = new ArrayList<TRect>(); int count = ninePlaceGridView.getChildCount(); for (int i = 0; i < count; i++) { if (ninePlaceGridView.getChildAt(i) instanceof TScallImageView) { TScallImageView scallImageView = (TScallImageView) ninePlaceGridView.getChildAt(i); int[] outLocation = new int[2]; scallImageView.getLocationInWindow(outLocation); Log.e("TAG","outLocation[0]:" + outLocation[0] + "outLocation[1]:" + outLocation[1]); TRect tRect = new TRect(outLocation[0],outLocation[1],scallImageView.getWidth(),scallImageView.getHeight()); originalRects.add(tRect); } else { continue; } } this.originalRects = originalRects; return originalRects; } public void showImageToWindow() { int[] outLocation = new int[2]; getLocationInWindow(outLocation); // originalRect = new TRect(getLeft(),getTop(),getWidth(),getHeight()); // originalRect = new TRect(outLocation[0],outLocation[1] - TKCUtils.getStatusBarHeight(getContext()),getWidth(),getHeight()); originalRect = new TRect(outLocation[0],outLocation[1],getWidth(),getHeight()); imageListBgView = new TImageListBgView(getContext(),originalRect,this.imageId,this.imageIds,currentIndex); imageListBgView.imageId = imageId; imageListBgView.originalRects = getOriginalRects(); imageListBgView.startTransform(TScallImageView.STATE_TRANSFORM_IN); } }
TImageListBgView:图片放大缩小动画,横向滑动浏览等逻辑处理类
- 点击手机的返回按键,缩小图片:这里需要注意一点,在window上添加视图后点击手机的返回按键,不会响应当前的Activity,因此需要在添加在window上的视图TImageListBgView内重写public boolean dispatchKeyEvent(KeyEvent event)方法来实现:
/**因此View添加在Window,点击手机返回按钮无法响应, * 重写此方法可以处理点击手机返回的逻辑处理,缩小图片到原位置 * @param event * @return */ @Override public boolean dispatchKeyEvent(KeyEvent event) {//2-4 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { if (mState == TScallImageView.STATE_TRANSFORM_IN) { startTransform(TScallImageView.STATE_TRANSFORM_OUT); return true; } } return super.dispatchKeyEvent(event); }
package com.tikeyc.tnineplacegridviewlibrary.TNinePlaceGridView; import android.animation.Animator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; import android.graphics.Color; import android.graphics.PixelFormat; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.WindowManager; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import com.squareup.picasso.Picasso; import java.util.List; /** * Created by public1 on 2017/5/23. */ public class TImageListBgView extends RelativeLayout { public int mState = TScallImageView.STATE_NORMAL; private TRect originalRect; public List<TRect> originalRects; public Object imageId; public List<Object> imageIds; public int currentIndex; private ImageView animationIV; private LinearLayout gridViewBgView; private GridView gridView; private TPageHorizatalScrollView horizontalScrollView; private TPageControl pageControl; public TImageListBgView(Context context, TRect originalRect,Object imageId,List<Object> imageIds,int currentIndex) { super(context); this.originalRect = originalRect; this.imageId = imageId; this.imageIds = imageIds; this.currentIndex = currentIndex; setBackgroundColor(Color.TRANSPARENT); initSubViews(); } public TImageListBgView(Context context) { super(context); } public TImageListBgView(Context context, AttributeSet attrs) { super(context, attrs); } public TImageListBgView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } /**因此View添加在Window,点击手机返回按钮无法响应, * 重写此方法可以处理点击手机返回的逻辑处理,缩小图片到原位置 * @param event * @return */ @Override public boolean dispatchKeyEvent(KeyEvent event) {//2-4 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { if (mState == TScallImageView.STATE_TRANSFORM_IN) { startTransform(TScallImageView.STATE_TRANSFORM_OUT); return true; } } return super.dispatchKeyEvent(event); } @Override public boolean dispatchKeyEventPreIme(KeyEvent event) {//1-3 return super.dispatchKeyEventPreIme(event); } private WindowManager windowManager; private void initSubViews() { // initImageListBgView(); // initAnimationIV(); // initHorizontalScrollView(); // initGridView(); // initPageControl(); } private void initImageListBgView() { Activity activity = (Activity) getContext(); windowManager = activity.getWindowManager(); WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); layoutParams.width = TRect.getScreenWidth(getContext()); layoutParams.height = TRect.getScreenHeight(getContext()); //FLAG_LAYOUT_IN_SCREEN layoutParams.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN; layoutParams.format = PixelFormat.RGBA_8888;//让背景透明,放大过程可以看到当前界面 layoutParams.verticalMargin = 0; windowManager.addView(this,layoutParams); } private void initAnimationIV() { animationIV = new ImageView(getContext()); // imageView.setBackgroundColor(Color.RED); animationIV.setScaleType(ImageView.ScaleType.FIT_CENTER); LayoutParams params = new LayoutParams(originalRect.getWidth(),originalRect.getHeight()); params.leftMargin = originalRect.getLeft(); params.topMargin = originalRect.getTop(); addView(animationIV,params); // Picasso.with(getContext()).load("http://ww2.sinaimg.cn/mw690/9e6995c9gw1f2uu70bzohj209q06g3yw.jpg").into(animationIV); if (imageId instanceof Integer) { animationIV.setImageResource((Integer) imageId); } else { Picasso.with(getContext()).load((String) imageId).into(animationIV); } } private void initHorizontalScrollView() { horizontalScrollView = new TPageHorizatalScrollView(getContext()); LayoutParams hsLayoutParams = new LayoutParams(TRect.getScreenWidth(getContext()),TRect.getScreenHeight(getContext())); hsLayoutParams.leftMargin = 0; hsLayoutParams.topMargin = 0; addView(horizontalScrollView,hsLayoutParams); horizontalScrollView.mBaseScrollX = currentIndex*TRect.getScreenWidth(getContext()); horizontalScrollView.setOnScrollToIndexListen(new TPageHorizatalScrollView.OnScrollToIndexListen() { @Override public void scrollToIndex(int index) { currentIndex = index; if (currentIndex >= imageIds.size()){ currentIndex = imageIds.size() - 1; } else if (currentIndex < 0) { currentIndex = 0; } Log.e("TAG","currentIndex" + currentIndex); if (imageId instanceof Integer) { animationIV.setImageResource((Integer) imageIds.get(currentIndex)); } else { Picasso.with(getContext()).load((String) imageIds.get(currentIndex)).into(animationIV); } originalRect = originalRects.get(currentIndex); pageControl.setCurrentPage(currentIndex); } }); int numColumns = imageIds.size(); gridViewBgView = new LinearLayout(getContext()); LinearLayout.LayoutParams testParams = new LinearLayout.LayoutParams(TRect.getScreenWidth(getContext())*numColumns,TRect.getScreenHeight(getContext())); horizontalScrollView.addView(gridViewBgView,testParams); } private void initGridView() { int numColumns = imageIds.size(); // gridView = new GridView(getContext()); gridView.setNumColumns(numColumns); gridView.setColumnWidth(TRect.getScreenWidth(getContext())); LinearLayout.LayoutParams gridViewLayoutParams = new LinearLayout.LayoutParams(TRect.getScreenWidth(getContext())*numColumns,TRect.getScreenHeight(getContext())); gridViewLayoutParams.leftMargin = 0; gridViewLayoutParams.topMargin = 0; gridViewBgView.addView(gridView,gridViewLayoutParams); final TImageGridViewAdapter adapter = new TImageGridViewAdapter(getContext()); adapter.imageIds = this.imageIds; gridView.setAdapter(adapter); adapter.setOnItemClickListener(new TImageGridViewAdapter.OnItemClickListener() { @Override public void onItemClick(int i, View view) { startTransform(TScallImageView.STATE_TRANSFORM_OUT); } }); // gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { // @Override // public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { // startTransform(TScallImageView.STATE_TRANSFORM_OUT); // } // }); } private void initPageControl() { pageControl = new TPageControl(getContext(),null); pageControl.setPageNumber(imageIds.size()); pageControl.setSelectedColor(Color.RED); LayoutParams layoutParams = new LayoutParams(TRect.getScreenWidth(getContext()),40); layoutParams.topMargin = TRect.getScreenHeight(getContext()) - 100; addView(pageControl,layoutParams); } /**放大缩小动画 * @param state */ public void startTransform(final int state) { final int duration = 300; ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setDuration(duration); valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); if (state == TScallImageView.STATE_TRANSFORM_IN) { setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); mState = TScallImageView.STATE_TRANSFORM_IN; gridViewBgView.setVisibility(INVISIBLE); pageControl.setVisibility(INVISIBLE); // PropertyValuesHolder scaleHolder = PropertyValuesHolder.ofFloat("scale", mTransfrom.startScale, mTransfrom.endScale); PropertyValuesHolder leftHolder = PropertyValuesHolder.ofFloat("left",originalRect.getLeft(), 0); PropertyValuesHolder topHolder = PropertyValuesHolder.ofFloat("top", originalRect.getTop(), 0); PropertyValuesHolder widthHolder = PropertyValuesHolder.ofFloat("width", originalRect.getWidth(), TRect.getScreenWidth(getContext())); PropertyValuesHolder heightHolder = PropertyValuesHolder.ofFloat("height", originalRect.getHeight(), TRect.getScreenHeight(getContext())); PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofInt("alpha", 0, 255); valueAnimator.setValues(leftHolder, topHolder, widthHolder, heightHolder, alphaHolder); } else { // setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); gridViewBgView.setVisibility(INVISIBLE); pageControl.setVisibility(INVISIBLE); animationIV.setVisibility(VISIBLE); setBackgroundColor(Color.TRANSPARENT); mState = TScallImageView.STATE_TRANSFORM_OUT; // PropertyValuesHolder scaleHolder = PropertyValuesHolder.ofFloat("scale", mTransfrom.endScale, mTransfrom.startScale); PropertyValuesHolder leftHolder = PropertyValuesHolder.ofFloat("left", animationIV.getLeft(), originalRect.getLeft()); PropertyValuesHolder topHolder = PropertyValuesHolder.ofFloat("top", animationIV.getTop(), originalRect.getTop()); PropertyValuesHolder widthHolder = PropertyValuesHolder.ofFloat("width", animationIV.getWidth(), originalRect.getWidth()); PropertyValuesHolder heightHolder = PropertyValuesHolder.ofFloat("height", animationIV.getHeight(), originalRect.getHeight()); PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofInt("alpha", 255, 0); valueAnimator.setValues(leftHolder, topHolder, widthHolder, heightHolder, alphaHolder); // Handler handler = new Handler(){ // @Override // public void handleMessage(Message msg) { // super.handleMessage(msg); // animationIV.setScaleType(ImageView.ScaleType.CENTER_CROP);//根据九宫格中的图片的显示模式设置 // } // }; // handler.sendEmptyMessageDelayed(0,duration*9/10); } valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public synchronized void onAnimationUpdate(ValueAnimator animation) { // mTransfrom.scale = (Float) animation.getAnimatedValue("scale"); Float left = (Float) animation.getAnimatedValue("left"); Float top = (Float) animation.getAnimatedValue("top"); Float width = (Float) animation.getAnimatedValue("width"); Float height = (Float) animation.getAnimatedValue("height"); Integer mBgAlpha = (Integer) animation.getAnimatedValue("alpha"); LayoutParams layoutParams = new LayoutParams(width.intValue(),height.intValue()); layoutParams.leftMargin = left.intValue(); layoutParams.topMargin = top.intValue(); animationIV.setLayoutParams(layoutParams); setAlpha(mBgAlpha); } }); final TImageListBgView[] imageListBgView = {this}; valueAnimator.addListener(new ValueAnimator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { /* * 如果是进入的话,当然是希望最后停留在center_crop的区域。但是如果是out的话,就不应该是center_crop的位置了 * , 而应该是最后变化的位置,因为当out的时候结束时,不回复视图是Normal,要不然会有一个突然闪动回去的bug */ // TODO 这个可以根据实际需求来修改 if (mState == TScallImageView.STATE_TRANSFORM_IN) { horizontalScrollView.baseSmoothScrollTo(0); setBackgroundColor(Color.BLACK); pageControl.setVisibility(VISIBLE); Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); gridViewBgView.setVisibility(VISIBLE); animationIV.setVisibility(INVISIBLE); } }; handler.sendEmptyMessageDelayed(0, duration); } else if (mState == TScallImageView.STATE_TRANSFORM_OUT) { gridViewBgView.removeView(gridView); gridView = null; horizontalScrollView.removeView(gridViewBgView); gridViewBgView = null; removeView(animationIV); animationIV = null; removeView(pageControl); pageControl = null; windowManager.removeView(imageListBgView[0]); imageListBgView[0] = null; } } @Override public void onAnimationCancel(Animator animation) { } }); valueAnimator.start(); } }
如何使用,非常之简单
- List<List<Object>> imageNames2D = new ArrayList<List<Object>>(); List<Object> imageNames = new ArrayList<Object>(); imageNames2D.add(imageNames); imageNames.add(Object); - TNinePlaceGridView ninePlaceGridView = (TNinePlaceGridView) view.findViewById(R.id.ninePlaceGridView); - ninePlaceGridView.setImageNames(imageNames);
如下代码示例:
public class MainActivity extends AppCompatActivity { @ViewInject(R.id.listView) private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); x.view().inject(this); init(); } private void init() { List<List<Object>> imageNames2D = new ArrayList<List<Object>>(); for (int i = 0; i < 30; i++) { ArrayList<Object> imageNames = new ArrayList<Object>(); Random random = new Random(); for (int j = 0; j <= random.nextInt(8); j++) { if (j%2 == 0) { imageNames.add(R.mipmap.beauty); // imageNames.add("http://7xi8d6.com1.z0.glb.clouddn.com/20171011084856_0YQ0jN_joanne_722_11_10_2017_8_39_5_505.jpeg"); } else { imageNames.add(R.mipmap.glenceluanch); // imageNames.add("http://7xi8d6.com1.z0.glb.clouddn.com/2017-10-10-sakura.gun_10_10_2017_12_33_34_751.jpg"); } } imageNames2D.add(imageNames); } ListViewAdapter listViewAdapter = new ListViewAdapter(this); listViewAdapter.imageNames2D = imageNames2D; listView.setAdapter(listViewAdapter); } @Override protected void onResume() { super.onResume(); } @Override protected void onPause() { super.onPause(); } @Override protected void onDestroy() { super.onDestroy(); } private class ListViewAdapter extends BaseAdapter { private Context context; public List<List<Object>> imageNames2D; public ListViewAdapter(Context context) { this.context = context; } @Override public int getCount() { if (imageNames2D != null) return imageNames2D.size(); return 0; } @Override public Object getItem(int i) { return null; } @Override public long getItemId(int i) { return 0; } private class ViewHelper { CircleImageView imageViewIcon; TextView textViewNickName; TNinePlaceGridView ninePlaceGridView; } @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHelper viewHelper; if (view == null) { view = View.inflate(context,R.layout.timage_listactivity_listview_item,null); viewHelper = new ViewHelper(); viewHelper.imageViewIcon = (CircleImageView) view.findViewById(R.id.imageViewIcon); viewHelper.textViewNickName = (TextView) view.findViewById(R.id.textViewNickName); viewHelper.ninePlaceGridView = (TNinePlaceGridView) view.findViewById(R.id.ninePlaceGridView); view.setTag(viewHelper); } else { viewHelper = (ViewHelper) view.getTag(); } List<Object> imageNames = this.imageNames2D.get(i); viewHelper.ninePlaceGridView.setImageNames(imageNames); return view; } } }