一、原理

ViewPager是Android中使用频率相对较高的view组件,同时对滑动过程中的事件进行了处理,因此非常适合轮播图。关于轮播图的实现,有很多方法,使用HorizontalView或者RecylerView也可以实现,但是需要处理fling操作,这里我们用ViewPager避免这些工作。

网上有很多关于ViewPager轮播的轮播实现,其原理大多数给PagerAdapter的getCount 放大N倍,N大于100,1000等。这里我们使用另一种思路,数据映射。

数据映射方案:

假设原始数据有N张图片数据,我们将数据N+2,然后将原来的第一张图片放到新的 索引为N+1的位置,原来的最后一张图片放到第一张图片,这样构建了一个新的数据。

当图片滑动到 position==0 时,我们使用viewPager.setCurrentItem(N,false) ,当position=N+1时,我们使用viewPager.setCurrentItem(1,false);便可实无限滑动。

当然,以上方案可行,也很简单,但是却破坏了原始数据,我们可以通过算法实现原始数据不被破坏的实现方式,计算出真实的数据索引。

 private int getRealPosition(int position) {            int realPosition = position;            if(InnerWrapperPagerAdapter.this.getCount()>1){                if(position==0){                    realPosition = (getCount()-2)-1;                }else if(position==getCount()-1){                    realPosition = 0;                }else{                    realPosition = position-1;                }            }            return realPosition;        }

二、代码实现

public class AutoBannerView extends ViewPager implements Handler.Callback {    private OnPagerChangeListener mOpageChangeListener;    public static long TIME_WAIT = 3000;  //每3秒轮播一次    private boolean isPlaying = false;    private OnPagerSelectedListener mOnPagerSelectedListener;    private boolean lastStateIsPlaying = false; //停止轮播之前的状态    //private   static  AutoBannerRunnable autoRunnable = null;    private final  Handler  mTaskHandler;    private static final int ACTION_PLAY = 1024*1024;    public AutoBannerView(Context context) {        this(context,null);    }    public AutoBannerView(Context context, AttributeSet attrs) {        super(context, attrs);        setOverScrollMode(OVER_SCROLL_NEVER);        setOffscreenPageLimit(5);        if(mOpageChangeListener==null){            mOpageChangeListener = new OnPagerChangeListener(this);        }        mTaskHandler = new Handler(Looper.getMainLooper(),this);    }    public void setOnPagerSelectedListener(OnPagerSelectedListener mOnPagerSelectedListener) {        this.mOnPagerSelectedListener = mOnPagerSelectedListener;    }    @Override    public boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params) {        return super.addViewInLayout(child, index, params);    }    @Override    protected boolean addViewInLayout(View child, int index, ViewGroup.LayoutParams params, boolean preventRequestLayout) {        return super.addViewInLayout(child, index, params, preventRequestLayout);    }    @Override    public void setAdapter(PagerAdapter adapter) {        if (null != getAdapter()) {            removeOnPageChangeListener(mOpageChangeListener);        }        if (null == adapter) {            super.setAdapter(null);        } else {            super.setAdapter(new InnerWrapperPagerAdapter(adapter,this));            addOnPageChangeListener(mOpageChangeListener);            if(adapter.getCount()>1){                setCurrentItem(1,false);  //getCount>1 ,初始化时默认显示原始数据的第0位,也就是新的PagerAdapter的第二位                startPlay();            }else if(adapter.getCount()>0){                mOpageChangeListener.onPageSelected(0);            }        }    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        finishResetPosition();        final ViewParent parent = this.getParent();        switch (ev.getActionMasked()){            case MotionEvent.ACTION_DOWN:            case MotionEvent.ACTION_MOVE:                if (parent != null) {                    parent.requestDisallowInterceptTouchEvent(true);                    //解决ViewPager嵌套ViewPager导致无法滑动的问题                }                if(isPlaying){                    stopPlay();                }                break;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                if (parent != null) {                    parent.requestDisallowInterceptTouchEvent(false);                    //解决ViewPager嵌套ViewPager导致无法滑动的问题                }                if(lastStateIsPlaying){                    startPlay();                }                break;        }        return super.onTouchEvent(ev);    }    public PagerAdapter getRealAdapter() {        final PagerAdapter adapter = getAdapter();        if( adapter instanceof  InnerWrapperPagerAdapter){            return ((InnerWrapperPagerAdapter) adapter).getTargetPagerAdapter();        }        return adapter;    }    public static class AdapterDataSetObserver extends  DataSetObserver{        private InnerWrapperPagerAdapter  innerWrapperPagerAdapter;        private AutoBannerView autoBannerView;        public AdapterDataSetObserver(InnerWrapperPagerAdapter innerWrapperPagerAdapter,AutoBannerView autoBannerView) {            this.innerWrapperPagerAdapter = innerWrapperPagerAdapter;            this.autoBannerView  = autoBannerView;        }        @Override        public void onChanged() {            super.onChanged();            innerWrapperPagerAdapter.notifyDataSetChanged();            if(innerWrapperPagerAdapter.getCount()>1){                final int currentItem = this.autoBannerView.getCurrentItem();                if(currentItem==0){                    this.autoBannerView.setCurrentItem(1,false);                }                if(this.autoBannerView.isPlaying || this.autoBannerView.lastStateIsPlaying){                    this.autoBannerView.startPlay();                }            }            if(innerWrapperPagerAdapter.getCount()>0 &&this.autoBannerView.mOpageChangeListener!=null) {                this.autoBannerView.mOpageChangeListener.onPageSelected(this.autoBannerView.getCurrentItem());            }        }    }    /**     * 包装PagerAdapter,实现数据映射     */    private static class  InnerWrapperPagerAdapter extends PagerAdapter{        private final AdapterDataSetObserver adapterDataSetObserver;        private PagerAdapter mPagerAdapter;        public InnerWrapperPagerAdapter(PagerAdapter pagerAdapter,AutoBannerView autoBannerView) {            this.mPagerAdapter = pagerAdapter;            this.adapterDataSetObserver = new AdapterDataSetObserver(this,autoBannerView);            if(this.mPagerAdapter!=null){                this.mPagerAdapter.registerDataSetObserver(this.adapterDataSetObserver);            }        }        public PagerAdapter getTargetPagerAdapter() {            return mPagerAdapter;        }        @Override        public int getCount() {            if(mPagerAdapter!=null) {  //如果数据大于1,说明可以轮播                return mPagerAdapter.getCount() > 1 ? mPagerAdapter.getCount() + 2 : mPagerAdapter.getCount();            }            return 0;        }        @Override        public boolean isViewFromObject(View view, Object object) {            if(mPagerAdapter!=null) {                return mPagerAdapter.isViewFromObject(view, object);            }            return false;        }        @Override        public Object instantiateItem(ViewGroup container, int position) {            if(mPagerAdapter!=null) {                int realPosition = getRealPosition(position);                return mPagerAdapter.instantiateItem(container, realPosition);            }            return super.instantiateItem(container,position);        }        @Override        public void destroyItem(ViewGroup container, int position, Object object) {            if(mPagerAdapter!=null) {                int realPosition = getRealPosition(position);                mPagerAdapter.destroyItem(container, realPosition, object);            }else{                super.destroyItem(container,position,object);            }        }        private int getRealPosition(int position) {            int realPosition = position;            if(InnerWrapperPagerAdapter.this.getCount()>1){                if(position==0){                    realPosition = (getCount()-2)-1;                }else if(position==getCount()-1){                    realPosition = 0;                }else{                    realPosition = position-1;                }            }            return realPosition;        }        @Override        public int getItemPosition(Object object) {            if(mPagerAdapter!=null){                return mPagerAdapter.getItemPosition(object);            }            return super.getItemPosition(object);        }        @Override        public CharSequence getPageTitle(int position) {            if(mPagerAdapter!=null) {                int realPosition = getRealPosition(position);                return mPagerAdapter.getPageTitle(realPosition);            }else{                return super.getPageTitle(position);            }        }        @Override        public float getPageWidth(int position) {            if(mPagerAdapter!=null){                int realPosition = getRealPosition(position);                return mPagerAdapter.getPageWidth(realPosition);            }            return super.getPageWidth(position);        }        @Override        public void startUpdate(ViewGroup container) {            if(mPagerAdapter!=null) {                mPagerAdapter.startUpdate(container);            }else{                super.startUpdate(container);            }        }        @Override        public void setPrimaryItem(ViewGroup container, int position, Object object) {            if(mPagerAdapter!=null) {                int realPosition = getRealPosition(position);                mPagerAdapter.setPrimaryItem(container, realPosition, object);            }else{                super.setPrimaryItem(container,position,object);            }        }        @Override        public void finishUpdate(ViewGroup container) {            if(mPagerAdapter!=null)            {                mPagerAdapter.finishUpdate(container);            }else{                super.finishUpdate(container);            }        }        @Override        public Parcelable saveState() {            if(mPagerAdapter!=null)            {                return mPagerAdapter.saveState();            }            return super.saveState();        }        @Override        public void restoreState(Parcelable state, ClassLoader loader) {            if(mPagerAdapter!=null) {                mPagerAdapter.restoreState(state, loader);            }else{                super.restoreState(state,loader);            }        }        public void setPagerAdapter(PagerAdapter pagerAdapter) {            this.mPagerAdapter = pagerAdapter;        }    }    public int getClientWidth(){        return getMeasuredWidth() - getPaddingLeft() - getPaddingRight();    }    private static class OnPagerChangeListener implements ViewPager.OnPageChangeListener{        private final AutoBannerView mAutoBannerView;        public OnPagerChangeListener(AutoBannerView autoBannerView) {            this.mAutoBannerView = autoBannerView;        }        @Override        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {            if(shouldCancelHandle()) return;        }        @Override        public void onPageSelected(int position) {            if(shouldCancelHandle()) return;              notifyUpdateIndictor(position);        }        public void notifyUpdateIndictor(int position) {            final int realPosition = getRealPosition(position);            if(this.mAutoBannerView.mOnPagerSelectedListener!=null){                final PagerAdapter adapter = this.mAutoBannerView.getAdapter();                final int count = adapter.getCount();                if(count>1) {                    this.mAutoBannerView.mOnPagerSelectedListener.onPagerItemSelected(realPosition);                }else if(count==1){                    this.mAutoBannerView.mOnPagerSelectedListener.onPagerItemSelected(1);                }else{                    this.mAutoBannerView.mOnPagerSelectedListener.onPagerItemSelected(0);                }            }        }        private int getRealPosition(int position) {            int realPosition = position;            if(this.mAutoBannerView .getAdapter().getCount()>1){                PagerAdapter adapter = this.mAutoBannerView.getAdapter();  //1                if(adapter instanceof InnerWrapperPagerAdapter){                    adapter =   ((InnerWrapperPagerAdapter) adapter).getTargetPagerAdapter();                }                if(position==0){                    realPosition = adapter.getCount();                }else if(position==adapter.getCount()+1){                    realPosition = 1;                }            }            return realPosition;        }        @Override        public void onPageScrollStateChanged(int state) {            //在该方法中处理首尾切换,其他方法会产生动画中断问题            if(shouldCancelHandle()) return;            if(state!=SCROLL_STATE_IDLE){ //当动画执行完,立即切换                this.mAutoBannerView.finishResetPosition();            }        }        private boolean shouldCancelHandle() {            return this.mAutoBannerView==null || mAutoBannerView.getAdapter()==null;        }    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();        if(lastStateIsPlaying){  //如果之前是轮播的,那么继续轮播            startPlay();        }    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        if(isPlaying) {            stopPlay();// 如果从window中移除掉,停止轮播        }        onInvisibleToUser();    }    private void onInvisibleToUser() {        final int currentItem = getCurrentItem();        PagerAdapter adapter = getAdapter();        if(adapter instanceof InnerWrapperPagerAdapter){            adapter =   ((InnerWrapperPagerAdapter) adapter).getTargetPagerAdapter();        }        if(adapter!=null && adapter.getCount()>1 && currentItem>0) {            setCurrentItem(currentItem - 1);            setCurrentItem(currentItem);        }    }    @Override    protected void onVisibilityChanged(View changedView, int visibility) {        super.onVisibilityChanged(changedView, visibility);        if (visibility == VISIBLE) {            if(lastStateIsPlaying){  //如果之前是轮播的,那么继续轮播                startPlay();            }        } else if (visibility == INVISIBLE || visibility == GONE) {            if(isPlaying) {                stopPlay();// 如果从window中移除掉,停止轮播            }            onInvisibleToUser();        }    }    public interface  OnPagerSelectedListener{        //用于监听真实的滑动位置,方便外部使用        public void onPagerItemSelected(int position);    }    public void startPlay(){        stopPlay();        isPlaying = true;       /* postDelayed(autoRunnable,TIME_WAIT);*/        mTaskHandler.sendEmptyMessageDelayed(ACTION_PLAY,TIME_WAIT);    }    public void stopPlay() {        lastStateIsPlaying = isPlaying==true;        isPlaying = false;        mTaskHandler.removeMessages(ACTION_PLAY);    }    @Override    public boolean handleMessage(Message msg) {        if(msg==null) return false;        int action = msg.what;        switch (action){            case ACTION_PLAY:                this.showNext();                return  true;        }        return false;    }    private long lastExecuteTimestramp = 0;    private boolean finishResetPosition() {        if(!(this.getAdapter() instanceof InnerWrapperPagerAdapter)) return false;        int currentItem = this.getCurrentItem();        if(this.getAdapter().getCount()>1){            InnerWrapperPagerAdapter adapter = (InnerWrapperPagerAdapter) this.getAdapter();            if(currentItem==0 ){                //this.setCurrentItem(adapter.getCount()-2,false);                scrollToItem(adapter.getCount()-2,adapter.getCount());                return  true;            }else if(currentItem==adapter.getCount()-1){                scrollToItem(1,adapter.getCount());              /*  this.setCurrentItem(1,false)*/;                return true;            }        }        return false;    }    public void showNext() {        if(Looper.myLooper()!=Looper.getMainLooper()) return; //要求在主线程工作        final long currentTimestramp = System.currentTimeMillis();        final long diff = (currentTimestramp - lastExecuteTimestramp);        lastExecuteTimestramp = currentTimestramp;        PagerAdapter adapter = this.getAdapter();        if(null==adapter || adapter.getCount()<=1) return;        if(!this.isPlaying) return; //停止执行        int currentItem = this.getCurrentItem();        if (currentItem > 0 && currentItem < (adapter.getCount() - 1)) {            if(currentItem==1){                scrollToItem(1,adapter.getCount());            }            this.setCurrentItem(currentItem + 1, true);        }        if(diff

三、使用方法

用法很简单我,按照ViewPager的用法即可,但是需要注意的一点是,我们仍然需要进一步封装,因此仅仅依靠自定义的轮播图,可能让人产生误解,因此我们可以进一步封装

public class SlidingBanner extends RelativeLayout implements AutoBannerView.OnPagerSelectedListener {    private AutoBannerView mAutoPlayViewPager;    private TextView mPositionTextView;    private OnPagerItemClickListener onPagerItemClickListener;    private ImageView.ScaleType scaleType = ImageView.ScaleType.FIT_XY;    private RotationPageTransformer pageTransformer;    private int offscreenPageLimit;    private int pageMargin;    public SlidingBanner(Context context) {        this(context,null);    }    public SlidingBanner(Context context, AttributeSet attrs) {        this(context, attrs,0);    }    public SlidingBanner(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        setScaleType(ImageView.ScaleType.FIT_XY);    }    public void setOnPagerItemClickListener(OnPagerItemClickListener onPagerItemClickListener) {        this.onPagerItemClickListener = onPagerItemClickListener;    }    public void setImageList(List imageList){        if(imageList==null){            imageList = new ArrayList<>();        }        if( !(mAutoPlayViewPager.getRealAdapter() instanceof SlidingPagerAdapter) ){            setPagerAdapter(new SlidingPagerAdapter(this, imageList));        }else{            SlidingPagerAdapter slidingPagerAdapter = (SlidingPagerAdapter) mAutoPlayViewPager.getRealAdapter();            slidingPagerAdapter.updateDatasource(imageList);        }    }    public boolean isEmptyBanner(){        if(mAutoPlayViewPager==null || mAutoPlayViewPager.getRealAdapter()==null){            return true;        }        return false;    }    public void hidePositionIndictor(){        if(mPositionTextView!=null) {            mPositionTextView.setVisibility(GONE);        }    }    public void showPositionIndictor(){        if(mPositionTextView!=null) {            mPositionTextView.setVisibility(VISIBLE);        }    }    public void setPagerAdapter(PagerAdapter pagerAdapter) {        if(mAutoPlayViewPager!=null){            mAutoPlayViewPager.setAdapter(pagerAdapter);        }    }    public PagerAdapter getPagerAdapter( ) {        return mAutoPlayViewPager.getRealAdapter();    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        if(mAutoPlayViewPager==null) {            mAutoPlayViewPager = createAutoPlayViewPager();            addView(mAutoPlayViewPager,0);        }        if(mPositionTextView ==null){            mPositionTextView = createPositionTextView();            addView(mPositionTextView,1);        }        mAutoPlayViewPager.setOnPagerSelectedListener(this);    }    private TextView createPositionTextView() {        TextView tv = new AppCompatTextView(this.getContext());        LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);        lp.addRule(ALIGN_PARENT_BOTTOM);        lp.addRule(ALIGN_PARENT_RIGHT);        lp.rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,8,getResources().getDisplayMetrics());        lp.bottomMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,4,getResources().getDisplayMetrics());        PaintDrawable shapeDrawable = new PaintDrawable(0xAA000000);        shapeDrawable.setCornerRadius(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,8,getResources().getDisplayMetrics()));        tv.setBackground(shapeDrawable);        final int px = DisplayUtil.dp2px(getContext(), 8);        tv.setPadding(px,0,px,0);        tv.setLayoutParams(lp);        tv.setTextColor(Color.WHITE);        tv.setTextSize(12);        return  tv;    }    private AutoBannerView createAutoPlayViewPager() {        AutoBannerView autoPlayViewPager = new AutoBannerView(getContext());        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);        autoPlayViewPager.setLayoutParams(lp);        if(this.pageTransformer!=null){            autoPlayViewPager.setPageTransformer(true,this.pageTransformer);        }        if(this.offscreenPageLimit!=0){            autoPlayViewPager.setOffscreenPageLimit(this.offscreenPageLimit);        }        autoPlayViewPager.setPageMargin(this.pageMargin);        return autoPlayViewPager;    }    @Override    public void onPagerItemSelected(int position) {        if(mAutoPlayViewPager==null || mAutoPlayViewPager.getRealAdapter()==null) return;        final PagerAdapter adapter = mAutoPlayViewPager.getRealAdapter();        updateIndictor(position,adapter.getCount());    }    private void updateIndictor(int position,int count) {        if(mPositionTextView==null) return;        mPositionTextView.setText(String.format("%s/%s",position,count));    }    public ImageView.ScaleType getScaleType() {        return scaleType;    }    public void setScaleType(ImageView.ScaleType scaleType) {        this.scaleType = scaleType;    }    public void startPlay() {        if(mAutoPlayViewPager!=null){            mAutoPlayViewPager.startPlay();        }    }    public void stopPlay(){        if(mAutoPlayViewPager!=null){            mAutoPlayViewPager.stopPlay();        }    }    public void setPageTransformer(RotationPageTransformer pageTransformer) {        this.pageTransformer = pageTransformer;        if(mAutoPlayViewPager!=null){            mAutoPlayViewPager.setPageTransformer(true,pageTransformer);        }    }    public void setOffscreenPageLimit(int offscreenPageLimit) {        this.offscreenPageLimit = offscreenPageLimit;        if(mAutoPlayViewPager!=null){            mAutoPlayViewPager.setOffscreenPageLimit(this.offscreenPageLimit);        }    }    public void setPageMargin(int pageMargin) {        this.pageMargin = pageMargin;        if(mAutoPlayViewPager!=null){            mAutoPlayViewPager.setPageMargin(20);        }    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();       // notifyImageViewInvalidate();    }    private void notifyImageViewInvalidate() {        if(mAutoPlayViewPager==null) return;        final List imageViews = AppUtils.getViews(mAutoPlayViewPager, ImageView.class);        if(imageViews==null || imageViews.size()==0) return;        for (ImageView imageView : imageViews){            if(imageView==null || imageView.getVisibility()==GONE) continue;            final Drawable drawable = imageView.getDrawable();            if(drawable==null){                imageView.setImageResource(R.drawable.defualt_img);            }else {                if (!drawable.isVisible()) {                    drawable.setVisible(true, false);                }else {                    drawable.invalidateSelf();                }            }        }    }    public final static  class  SlidingPagerAdapter  extends PagerAdapter{        private final SlidingBanner slidingBanner;        private List  imagelst;        public SlidingPagerAdapter(SlidingBanner slidingBanner, List  images){            this.slidingBanner = slidingBanner;            this.imagelst = new ArrayList<>();            this.imagelst.addAll(images);        }        @Override        public void startUpdate(ViewGroup container) {            super.startUpdate(container);            container.setEnabled(false);        }        @Override        public void finishUpdate(ViewGroup container) {            super.finishUpdate(container);            container.requestLayout();            container.invalidate();            container.setEnabled(true);        }        @Override        public int getItemPosition(Object object) {            return PagerAdapter.POSITION_NONE;        }        @Override        public int getCount() {            return imagelst.size();        }        @Override        public boolean isViewFromObject(View view, Object object) {            return view==object;        }        @Override        public Object instantiateItem(ViewGroup container, int position) {            View view = getView(container, position);            if(view.getParent()!= null){                final ViewGroup parent = ((ViewGroup)view.getParent());                parent.removeViewInLayout(view);            }            if(container instanceof AutoBannerView) {                ((AutoBannerView) container).addViewInLayout(view,-1,view.getLayoutParams());            }else{                container.addView(view);            }            addOnClickListenerToView(view,position,container);            return view;        }        private void addOnClickListenerToView(View view,int position ,ViewGroup container) {            view.setOnClickListener(new OnClickListener() {                @Override                public void onClick(View v) {                    int childIndex = position;                    if(slidingBanner.onPagerItemClickListener!=null) {                        slidingBanner.onPagerItemClickListener.onPagerItemClick(childIndex,view,container);                    }                }            });        }        private View getView(ViewGroup container,int position){            final LayoutInflater inflater = LayoutInflater.from(container.getContext());            final ImageView view = getImageView(inflater, position);           Glide.with(view).diskCacheStrategy(DiskCacheStrategy.ALL).load(imagelst.get(position)).placeholder(R.drawable.xsj_default_product_img).into(view);            return  view;        }        private ImageView getImageView(LayoutInflater inflater, int position) {            ImageView imageView = new AppImageView(inflater.getContext());            imageView.setImageResource(R.drawable.xsj_default_product_img);            ViewPager.LayoutParams lp = new ViewPager.LayoutParams();            imageView.setLayoutParams(lp);            if(slidingBanner.getScaleType()!=null){                imageView.setScaleType(slidingBanner.getScaleType());            }            return imageView;        }        @Override        public void destroyItem(ViewGroup container, int position, Object object) {            container.removeViewInLayout((View) object);        }        public void updateDatasource(List imageDataset) {            if(imageDataset==null || imageDataset.size()==0){                if(this.imagelst.size()>0){                    this.imagelst.clear();                    notifyDataSetChanged();                }                return;            }            if(this.imagelst.size()!=imageDataset.size()){                this.imagelst.clear();                this.imagelst.addAll(imageDataset);                notifyDataSetChanged();                return;            }            boolean isNeedUpdate = false;            for (int i=0;i

使用方法:

  slidingBanner.setImageList(entity);        slidingBanner.setOnPagerItemClickListener(this);        slidingBanner.startPlay();

更多相关文章

  1. Android(安卓)订餐APP(Sqlite数据库,完整的增删改查)
  2. 【安卓面试笔记】Content Provider(五)
  3. Android数据绑定(DataBinding)
  4. Android截屏方法总结
  5. Android(安卓)开发之详解 IPC 进程通信
  6. Android图片压缩,自己编译libjpeg
  7. Android使用KeyStore对数据进行加密的示例代码
  8. 安卓ListView详解
  9. android中如何通过硬件获取H264帧?

随机推荐

  1. 浅谈Android系统的基本体系结构与内存管
  2. Android开发者指南(7) —— App Install
  3. android declare-styleable的使用
  4. Android(安卓)Design新控件之TextInputLa
  5. Android控件:EditText之setOnEditorActio
  6. Android(安卓)API Guides---Calendar Pro
  7. Android(安卓)之 上下文菜单、选项菜单、
  8. Android学习笔记(20):时钟(AnalogClock和
  9. android 的反编译与防反编译
  10. 为 Android(安卓)平台开发一个输入法