项目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;
}
}
}