Android 轮播图从 0 到 1
轮播图是 Android 常用功能之一,效果大概是这样的:
之前我封装写了一个,基本达到了要求,是继承了 Fragment(当时脑袋肯定锈掉了),里面 Viewpager add Fragment,这次项目多处有轮播图,发现之前封装的不够用,简直漏洞百出:1、比如底部 point 的位置,之前固定在中间,现在可能要放在右下角,point 最好也能动态改图片;2、现在项目跟微信一样,底部 tab 切换,中间是 Fragment 替换,发现轮播图有问题,Fragment A 循环的 point 的 positoin 居然影响到了 Fragment B,照理,这是两个 BannerFragment,不会影响的啊,报以下错误:
java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's
contents without calling PagerAdapter#notifyDataSetChanged!
经过排查,找到了原因,因为 Viewpager add Fragment 我全部放在一个类,因此:
public static List<Object> bannerList = new ArrayList<>();
这里 static 坏事了,之前一个 banner 没有暴露出来。3、继承了 Fragment,引用比较麻烦,Fragment 有两者引用方法,xml 和代码,两者方式 addData 却报错;4、banner 没有写点击回调。
再次封装
综合以上问题,我进行了优化,继承 LinearLayout,当一个控件来引用,省去不必要的麻烦,底部 point 的位置可以设置:
pointLayout.setGravity(bannerPointGravity);
另外自定义了属性,动态设置 point 大小和图片,轮播图循环时间,也能代码设置,完整代码示例:
* Created by WuXiaolong on 2017/8/24.
* 个人博客:http://wuxiaolong.me
*/
public class BannerLayout extends LinearLayout {
private ViewPager viewPager;
private LinearLayout pointLayout;
private ScheduledExecutorService scheduler;
private int mPosition = 0;
private int mBannerCount = 1;
private Context context;
private Activity activity;
private int bannerPointSize;
private int bannerPointGravity;
private int bannerPointDrawableSelected, bannerPointDrawableUnselected;
private int bannerDelaySecond;
public BannerLayout(Context context) {
this(context, null);
}
public BannerLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BannerLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context, attrs);
}
private void initView(Context context, AttributeSet attrs) {
this.context = context;
activity = (Activity) context;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BannerLayout);
bannerPointSize = typedArray.getDimensionPixelSize(R.styleable.BannerLayout_bannerPointSize, 10);
bannerPointGravity = typedArray.getInt(R.styleable.BannerLayout_bannerPointGravity, Gravity.CENTER);
bannerDelaySecond = typedArray.getInt(R.styleable.BannerLayout_bannerDelaySecond, 5);
bannerPointDrawableSelected = typedArray.getResourceId(R.styleable.BannerLayout_bannerPointDrawableSelected, R.mipmap.point01);
bannerPointDrawableUnselected = typedArray.getResourceId(R.styleable.BannerLayout_bannerPointDrawableUnselected, R.mipmap.point02);
typedArray.recycle();
View view = View.inflate(context, R.layout.banner_view_pager, null);
addView(view);
viewPager = (ViewPager) view.findViewById(R.id.viewPager);
pointLayout = (LinearLayout) view.findViewById(R.id.pointLayout);
pointLayout.setGravity(bannerPointGravity);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
addPointLayout(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
public void start(List<Object> bannerList) {
bannerShutdown();
mBannerCount = bannerList.size();
BannerPagerAdapter bannerPagerAdapter = new BannerPagerAdapter(context, bannerList);
viewPager.setAdapter(bannerPagerAdapter);
addPointLayout(0);
startScheduler();
}
private void addPointLayout(int position) {
pointLayout.removeAllViews();
for (int i = 0; i < mBannerCount; i++) {
ImageView imageView = new ImageView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(bannerPointSize, bannerPointSize);
layoutParams.setMargins(10, 0, 0, 0);
imageView.setLayoutParams(layoutParams);
if (position == i) {
imageView.setImageResource(bannerPointDrawableSelected);
} else {
imageView.setImageResource(bannerPointDrawableUnselected);
}
pointLayout.addView(imageView);
}
}
private void startScheduler() {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
mPosition = viewPager.getCurrentItem();
if (mPosition < mBannerCount - 1) {
mPosition++;
} else {
mPosition = 0;
}
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
viewPager.setCurrentItem(mPosition);
}
});
}
}, 1, bannerDelaySecond, TimeUnit.SECONDS);
}
public void bannerShutdown() {
if (scheduler != null)
scheduler.shutdown();
}
private class BannerPagerAdapter extends PagerAdapter {
private List<Object> bannerList = new ArrayList<>();
private Context context;
BannerPagerAdapter(Context context, List<Object> bannerList) {
this.context = context;
this.bannerList.clear();
this.bannerList.addAll(bannerList);
}
@Override
public int getCount() {
return bannerList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
ImageView imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
Object object = bannerList.get(position);
//这里我封装了 Glide 4.0 的工具类,用于显示图片
ImageLoaderUtil.load(context, object, imageView);
container.addView(imageView);
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
public int dp2px(float var0) {
float var1 = context.getResources().getDisplayMetrics().density;
return (int) (var0 * var1 + 0.5F);
}
public void setBannerPointSize(int bannerPointSize) {
this.bannerPointSize = dp2px(bannerPointSize);
}
public void setBannerPointGravity(int bannerPointGravity) {
this.bannerPointGravity = bannerPointGravity;
pointLayout.setGravity(bannerPointGravity);
}
public void setBannerPointDrawableSelected(int bannerPointDrawableSelected) {
this.bannerPointDrawableSelected = bannerPointDrawableSelected;
}
public void setBannerPointDrawableUnselected(int bannerPointDrawableUnselected) {
this.bannerPointDrawableUnselected = bannerPointDrawableUnselected;
}
public void setBannerDelaySecond(int bannerDelaySecond) {
this.bannerDelaySecond = bannerDelaySecond;
}
}
其中自定义属性的attrs.xml:
<resources>
<declare-styleable name="BannerLayout">
<!--轮播图点的大小-->
<attr name="bannerPointSize" format="dimension" />
<!--轮播图点的位置,分别有左中右-->
<attr name="bannerPointGravity" format="enum">
<enum name="left" value="3" />
<enum name="center" value="17" />
<enum name="right" value="5" />
</attr>
<!--轮播图点选中的图片-->
<attr name="bannerPointDrawableSelected" format="reference" />
<!--轮播图点未选中的图片-->
<attr name="bannerPointDrawableUnselected" format="reference" />
<!--轮播图循环时间,单位秒-->
<attr name="bannerDelaySecond" format="integer" />
</declare-styleable>
</resources>
使用说明
xml
<com.wuxiaolong.bannersample.BannerLayout
android:id="@+id/bannerView"
android:layout_width="match_parent"
android:layout_height="198dp"
app:bannerDelaySecond="3"
app:bannerPointDrawableSelected="@drawable/gray_radius"
app:bannerPointDrawableUnselected="@drawable/white_radius"
app:bannerPointGravity="right"
app:bannerPointSize="10dp" />
调用:
public class MainActivity extends AppCompatActivity {
private BannerLayout bannerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bannerView = (BannerLayout) findViewById(R.id.bannerView);
List<Object> bannerList = new ArrayList<>();
bannerList.add(R.mipmap.horizontal_default);
bannerList.add("http://pic1.win4000.com/wallpaper/5/598161750eddb.jpg");
bannerList.add("http://pic1.win4000.com/wallpaper/4/597efb5b6aae8.jpg");
bannerView.setBannerPointSize(10);
bannerView.setBannerPointGravity(Gravity.CENTER);
bannerView.setBannerPointDrawableSelected(R.drawable.gray_radius);
bannerView.setBannerPointDrawableUnselected(R.mipmap.point01);
bannerView.setBannerDelaySecond(5);
//banner 设置方法完毕时最后调用 start 方法
bannerView.start(bannerList);
}
@Override
protected void onStop() {
super.onStop();
bannerView.bannerShutdown();
}
}
最后
欢迎加入Android进阶交流群;701740775。进群可免费领取一份最新技术大纲和Android进阶资料。请备注csdn
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
小视频开发过程中最关注的两点关键
小视频凭借它独有的特征在互联网领域获得了属于自己的一席之地,斩获搞笑、游戏、美食等行业后,在教育、财经等方面还拥有更加可观的发展前景。那么,在小视频开发过程中应该怎样结合它的能力实现业务上的突破呢?在小视频的拍摄阶段,用户通常最关注的的还是视频的清晰度和流畅度,我们可以从这几个环节入手,进行相关的优化。1.提升预览帧率摄像头采集数据再呈现到设备屏幕,一般采用GPU驱动渲染,确保渲染的实时性,还可以在一定程度上减少延迟和丢帧的情况。再者是针对人脸特效的渲染,我们通常可以采取3buffer的CPU回调方案,减少BUFFER资源等待所造成的帧率下降。2.提升录制帧率这里所说的录制是将视频进行编码的过程,整体采用CPU来直接渲染到硬件编码Surface,可以同时保留之前的buffer方案进行软件编码的适配,将编码的延迟和丢帧缩短到最小。 3.选择最优适配在开发过程中,移动终端的机型复杂的问题是非常令人头疼的。由于市面上机型的复杂度非常高,而且每一种机型的硬件能力、屏幕分辨率、性能等方面的指标都是千差万别的,要想最大限度的保证,能够在最低端机型上所呈现出的视频质量达到标准质量,那么就需要在提升清...
-
下一篇
对开源的认知
版权声明:本文为半吊子子全栈工匠(wireless_com,同公众号)原创文章,未经允许不得转载。 https://blog.csdn.net/wireless_com/article/details/86192092 没有开源软件,现在的互联网根本无法存在,开源的历史可以追溯到ARPANET建立。开源在今天已经不再是一个时髦的词了,对于互联网的开发者来说,它现在就像空气和水一样,就在我们的生活中。 来自https://octoverse.github.com 如今的主流开源参与者,不再只是个人爱好者,更多的是著名IT企业的员工,商业公司也纷纷支持。IT企业投入了大量人力在各个开源社区和项目上,包括开发测试,项目协调,运营推广等。 什么是开源 从软件的版权属性和发布方式上看,软件的分类如下: 开源软件被定义为描述其源码可以被公众使用的软件,并且此软件的使用,修改和分发也不受许可证的限制。开放源码软件通常是有copyright的,它的许可证可能包含这样一些限制:蓄意的保护它的开放源码状态,著者身份的公告,或者开发的控制。 简单的说,开源就是源代码开放和开源许可协议的选择。开源意味着用户可...
相关文章
文章评论
共有0条评论来说两句吧...

微信收款码
支付宝收款码