Android App图片轮播效果的组件化

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/voidreturn/article/details/75139689 简介一个通用的图片轮播效果的通用组件,方便开发者快速集成。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/voidreturn/article/details/75139689

简介

一个通用的图片轮播效果的通用组件,方便开发者快速集成。

初学者,其实应该实现一个自定义控件的,改天有空,在学习下吧,学习能力一般,以前也没写过java,这个组件都写了好久,惭愧啊。

背景

笔者参考http://blog.csdn.net/allen315410/article/details/39294343 学习了图片轮播效果的实现。在浏览代码的过程中,总觉得图片轮播的效果和Android Activity的耦合过高,如果一个开发者要集成该功能,会将整个功能代码和自己的App代码搅在一起,提高代码的复杂度。同时图片和图片文字描述存放在两个独立的ArrayList,这样的对应关系要由开发者手动维护,时刻关注对应关系正确性。
为什么需要组件:组件开发的目的,即让开发者用最少的代码,调用最少的接口,实现开发者的需求。
以上的描述是笔者对组件概念的最基本的认识,也是基于该原则,笔者基于http://blog.csdn.net/allen315410/article/details/39294343 进行了重构,实现了一个相对内聚的组件。

图片轮播的要素

如果一个开发者需要开发一个图片轮播的功能,开发者最少需要提供的元素有哪些:

  • 轮播的图片元素
  • 每个图片对应的文字描述
  • 轮播图片在布局中的位置
  • 图片描述在布局中的位置
  • 图片轮播的时间间隔

理论上讲,开发者只需要提高以上几个元素即可,剩下的就有组件完成吧。基于以上思路,开发者大概只需要完成类似代码即可:

public class MainActivity extends Activity {
    //提供一个ViewPagerItem类型数组,ViewPagerItem包括了图片信息和图片对应描述信息,采用一一对应的方式,方便维护
    private ViewPagerItem[] viewPagerItem = new ViewPagerItem[] {
            new ViewPagerItem(R.drawable.a, "0图片描述信息0"),
            new ViewPagerItem(R.drawable.b, "1图片描述信息1"),
            new ViewPagerItem(R.drawable.c, "2图片描述信息2"),
            new ViewPagerItem(R.drawable.d, "3图片描述信息3"),
            new ViewPagerItem(R.drawable.e, "4图片描述信息4"),
            new ViewPagerItem(R.drawable.e, "5图片描述信息5"),
    };

    private ViewPagerShow mViewPagerShow;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //提供一个layout布局容器,用来指定图片展示的位置
        LinearLayout container = (LinearLayout) findViewById(R.id.dot_container);
        //new一个ViewPagerShow,提供相应参数
        mViewPagerShow = new ViewPagerShow(viewPagerItem, this, (ViewPager)findViewById(R.id.vp), mHandler,
                (TextView)findViewById(R.id.title), container);

    }

    @Override
    protected void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
    }

    /**
     * 接收子线程传递过来的数据,调用ViewPagerShow提供的update方法,实现ui的更新
     */
    private Handler mHandler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            mViewPagerShow.update();
        };
    };

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
    }
}

浏览以上代码,不难发现该功能的加入,对开发者原有的代码的侵入范围不是很大。

用尽量少的代码,完成功能需求,是软件开发人员不断的追求。

轮播组件的实现

下面附上图片轮播效果组件的代码实现:

package com.example.image.view;

import android.content.Context;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static android.content.ContentValues.TAG;

/**
 * Created by image on 2017/7/14.
 */

class ViewPagerItem {
    public int iMageId;
    public String iMageTitle;

    public ViewPagerItem(int iMageId, String iMageTitle) {
        this.iMageId = iMageId;
        this.iMageTitle = iMageTitle;
    }
}

class ViewPagerAdapter extends PagerAdapter {
    private List<ImageView> iMageViews;

    public ViewPagerAdapter(List<ImageView> iMageViews) {
        this.iMageViews = iMageViews;
    }

    @Override
    public int getCount() {
        return iMageViews.size();
    }

    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
    }

    @Override
    public void destroyItem(ViewGroup view, int position, Object object) {
        // TODO Auto-generated method stub
        view.removeView(iMageViews.get(position));
    }

    @Override
    public Object instantiateItem(ViewGroup view, int position) {
        // TODO Auto-generated method stub
        view.addView(iMageViews.get(position));
        return iMageViews.get(position);
    }
}

class cloneView extends View {

    public cloneView(Context context) {
        super(context);
    }

    public cloneView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public cloneView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public cloneView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public Object clone(){
        Object o=null;
        try {
            o=super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }
}

class ViewPagerShow {
    private ArrayList<View> dots;
    private ViewPagerItem[] viewPagerItem;
    private List<ImageView> iMagesList;
    private Context context;
    private ViewPagerAdapter mViewPagerAdapter;
    private ViewPager mViewPager;
    private ScheduledExecutorService scheduledExecutorService;
    private Handler mHandler;
    private int currentItem = 0;
    private TextView titleText;
    private LinearLayout container;
    private View dot_focus, dot_unfocus;

    private class ViewPageTask implements Runnable{
        @Override
        public void run() {
            currentItem = (currentItem + 1) % viewPagerItem.length;
            mHandler.sendEmptyMessage(0);
        };
    }

    public void dotUpdate() {
        container.removeAllViews();
        View view;
        for (int i = 0; i < this.viewPagerItem.length; i++) {
            if (i == currentItem) {
                view = LayoutInflater.from(context).inflate(R.layout.dot_focus, null);
                container.addView(view);
            } else {
                view = LayoutInflater.from(context).inflate(R.layout.dot_unfocus, null);
                container.addView(view);
            }
        }
    }

    public ViewPagerShow(final ViewPagerItem[] viewPagerItem, Context context, ViewPager mViewPager, Handler mHandler,
                         final TextView titleText, LinearLayout container) {
        this.viewPagerItem = viewPagerItem;
        this.context = context;
        this.mViewPager = mViewPager;
        this.mHandler = mHandler;
        this.titleText = titleText;
        this.container = container;
        this.dot_focus = dot_focus;
        this.dot_unfocus = dot_unfocus;

        /* show first pic title */
        titleText.setText(viewPagerItem[0].iMageTitle);

        iMagesList = new ArrayList<ImageView>();
        for (int i = 0; i < this.viewPagerItem.length; i++) {
            ImageView imageView = new ImageView(context);
            imageView.setBackgroundResource(viewPagerItem[i].iMageId);
            imageView.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    // TODO Auto-generated method stub
                    Log.d(TAG, "onClick: onClick");;
                }
            });
            iMagesList.add(imageView);
        }
        dotUpdate();


        mViewPagerAdapter = new ViewPagerAdapter(iMagesList);
        mViewPager.setAdapter(mViewPagerAdapter);

        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                titleText.setText(viewPagerItem[position].iMageTitle);
                currentItem = position;
                dotUpdate();
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {

            }

            @Override
            public void onPageScrollStateChanged(int arg0) {

            }
        });

        scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutorService.scheduleWithFixedDelay(new ViewPageTask(), 5, 5, TimeUnit.SECONDS);
    }

    public void update() {
        mViewPager.setCurrentItem(currentItem);
        titleText.setText(viewPagerItem[currentItem].iMageTitle);
        dotUpdate();
    }
}

图片轮播的原理,基本都是参考http://blog.csdn.net/allen315410/article/details/39294343 该篇blog的介绍,这里做的主要的事情即把相关的接口进行一个整理,集中,剥离出一个通用的处理组件,方便开发者的集成。

目前该组件的实现还比较粗糙,待后续持续的更新,完善

文章写的很随意,时间精力关系很多细节没有讲到,最后附上github地址,供参考:https://github.com/imagec/ViewPager

目录
相关文章
|
28天前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
109 0
安卓项目:app注册/登录界面设计
|
2月前
|
存储 缓存 编解码
Android经典面试题之图片Bitmap怎么做优化
本文介绍了图片相关的内存优化方法,包括分辨率适配、图片压缩与缓存。文中详细讲解了如何根据不同分辨率放置图片资源,避免图片拉伸变形;并通过示例代码展示了使用`BitmapFactory.Options`进行图片压缩的具体步骤。此外,还介绍了Glide等第三方库如何利用LRU算法实现高效图片缓存。
61 20
Android经典面试题之图片Bitmap怎么做优化
|
2月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
104 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
2月前
|
存储 开发工具 Android开发
使用.NET MAUI开发第一个安卓APP
【9月更文挑战第24天】使用.NET MAUI开发首个安卓APP需完成以下步骤:首先,安装Visual Studio 2022并勾选“.NET Multi-platform App UI development”工作负载;接着,安装Android SDK。然后,创建新项目时选择“.NET Multi-platform App (MAUI)”模板,并仅针对Android平台进行配置。了解项目结构,包括`.csproj`配置文件、`Properties`配置文件夹、平台特定代码及共享代码等。
102 2
|
2月前
|
开发工具 Android开发 git
Android实战之组件化中如何进行版本控制和依赖管理
本文介绍了 Git Submodules 的功能及其在组件化开发中的应用。Submodules 允许将一个 Git 仓库作为另一个仓库的子目录,有助于保持模块独立、代码重用和版本控制。虽然存在一些缺点,如增加复杂性和初始化时间,但通过最佳实践可以有效利用其优势。
30 3
|
2月前
|
ARouter 测试技术 API
Android经典面试题之组件化原理、优缺点、实现方法?
本文介绍了组件化在Android开发中的应用,详细阐述了其原理、优缺点及实现方式,包括模块化、接口编程、依赖注入、路由机制等内容,并提供了具体代码示例。
42 2
|
2月前
|
XML Android开发 数据格式
🌐Android国际化与本地化全攻略!让你的App走遍全球无障碍!🌍
在全球化背景下,实现Android应用的国际化与本地化至关重要。本文以一款旅游指南App为例,详细介绍如何通过资源文件拆分与命名、适配布局与方向、处理日期时间及货币格式、考虑文化习俗等步骤,完成多语言支持和本地化调整。通过邀请用户测试并收集反馈,确保应用能无缝融入不同市场,提升用户体验与满意度。
80 3
|
27天前
|
安全 网络安全 Android开发
深度解析:利用Universal Links与Android App Links实现无缝网页至应用跳转的安全考量
【10月更文挑战第2天】在移动互联网时代,用户经常需要从网页无缝跳转到移动应用中。这种跳转不仅需要提供流畅的用户体验,还要确保安全性。本文将深入探讨如何利用Universal Links(仅限于iOS)和Android App Links技术实现这一目标,并分析其安全性。
148 0
|
2月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android应用开发中的多线程编程,涵盖基本概念、常见实现方式及最佳实践。主要内容包括主线程与工作线程的作用、多线程的多种实现方法(如 `Thread`、`HandlerThread`、`Executors` 和 Kotlin 协程),以及如何避免内存泄漏和合理使用线程池。通过有效的多线程管理,可以显著提升应用性能和用户体验。
67 10
|
2月前
|
XML 数据库 Android开发
10分钟手把手教你用Android手撸一个简易的个人记账App
该文章提供了使用Android Studio从零开始创建一个简单的个人记账应用的详细步骤,包括项目搭建、界面设计、数据库处理及各功能模块的实现方法。