zoukankan      html  css  js  c++  java
  • Android 实现九宫格、点击图片放大全屏浏览等

    项目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;
            }
        }
    
    }
  • 相关阅读:
    7个技巧,帮你完美搞定网页首图设计(必看)
    听说你想跳槽?ARM和PowerPC分析,你知道吗?(速进)
    C语言必学7大步骤!(必看)
    单片机电机必不可少的30条常识!你知道吗?(欢迎大家进行补充)
    单片机外围电路设计攻略(终结版)! 不看哭一年!
    3天”速成“嵌入式之后,我明白了六件事!!!
    前端就不需要掌握算法与数据结构?
    嵌入式软件必学知识总结!
    字节跳动2017客户端工程师实习生笔试题-第四题
    并查集
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/8929571.html
Copyright © 2011-2022 走看看