android自定义控件之滚动广告条

本文深入解析了如何在Android应用中实现滚动图片广告效果的源码细节,包括布局文件设计、关键代码实现及动画效果的优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在一些电子商务网站上经常能够看到一些滚动的广告条,许多软件在首次使用时也有类似的广告条,如图:

这里写图片描述

其实在github上有实现这种效果的控件,不过这东西做起来也是很简单,我们今天就来看看该怎么做。

先来看看布局文件:

?
1
2
3
4
<code class = "hljs xml" ><relativelayout android:layout_height= "match_parent" android:layout_width= "match_parent" tools:context= "com.example.customwidget2.MainActivity" xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" >
 
 
</android.support.v4.view.viewpager></relativelayout></code>

布局文件最上边是一个Viewpager,使用viewpager来实现图片的滚动效果,viewpager下边是一个linearlayout,这个布局文件中有两个东西,一个是textview,这是用来显示下边那一行字的,还有一个linearlayout,这是用来显示字下边的小点,小点的个数我们要根据图片的数量动态添加,所以现在先空着。

MainActivity.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<code class = "hljs java" > public class MainActivity extends Activity {
 
     private ViewPager mViewPager;
     // 图片都存放在这里
     private List<imageview> imageViewlist;
     private ImageView iv;
     private TextView imgDes;
     // 线程开关,当activity销毁后,线程也应该停止运行
     private boolean isStop = false ;
     private int previousPoint = 0 ;
     // 存放小点的布局文件
     private LinearLayout layoutPGroup;
     private String[] imageDescription = { "淮左名都,竹西佳处,解鞍少驻初程。" , "过春风十里。尽荠麦青青。" ,
             "自胡马窥江去后,废池乔木,犹厌言兵。" , "渐黄昏,清角吹寒。都在空城。" , "杜郎俊赏,算而今、重到须惊。" };
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         // 初始化
         init();
         //设置图片自动滚动
         new Thread( new Runnable() {
 
             @Override
             public void run() {
                 //如果activity未销毁则一直执行
                 while (!isStop) {
                     //先休息5秒钟
                     SystemClock.sleep( 5000 );
                     //以下代码发送到主线程中执行
                     runOnUiThread( new Runnable() {
 
                         @Override
                         public void run() {
                             mViewPager.setCurrentItem(mViewPager
                                     .getCurrentItem() + 1 );
                         }
                     });
                 }
             }
         }).start();
     }
 
     private void init() {
         mViewPager = (ViewPager) this .findViewById(R.id.viewpager);
         layoutPGroup = (LinearLayout) this .findViewById(R.id.show_pointer);
         imgDes = (TextView) this .findViewById(R.id.image_description);
         imageViewlist = new ArrayList<imageview>();
 
         // 先拿到图片id
         int [] ivIDs = new int [] { R.drawable.a, R.drawable.b, R.drawable.c,
                 R.drawable.d, R.drawable.e };
         // 遍历图片id
         for ( int id : ivIDs) {
             // 构造新的图片对象,并根据id给图片设置背景
             iv = new ImageView( this );
             iv.setBackgroundResource(id);
             // 所有的图片存放在imageViewlist中
             imageViewlist.add(iv);
 
             // 构造小点
             View v = new View( this );
             // 设置小点的宽和高
             LayoutParams params = new LayoutParams( 8 , 8 );
             // 设置小点的左边距
             params.leftMargin = 12 ;
             v.setLayoutParams(params);
             // 设置小点是否可用,默认都不可用,当不可用时,小点是透明的,否则是白色的
             v.setEnabled( false );
             // 设置小点的背景,这个背景是使用xml文件画的一个小圆点
             v.setBackgroundResource(R.drawable.pointer_selector);
             // 把小点添加到它的布局文件中
             layoutPGroup.addView(v);
         }
         // 计算应用打开时显示的第一项 Integer.MAX_VALUE /2 - 3=0
         int index = Integer.MAX_VALUE / 2 - 3 ;
         // 给mViewPager设置数据
         mViewPager.setAdapter( new MyPagerAdapter());
         // 给mViewPager设置页面滑动事件
         mViewPager.setOnPageChangeListener( new MyOnPageChangeListener());
 
         // 设置应用打开时显示的第一项,index的值为0
         // 使用这种方式得到的0,和直接写0有什么区别呢?
         // 直接写0,应用打开后不能直接向右滑动,因为viewpager中存image位置不能为负值,只能先向左滑动
         // 这种方式得到的0,可以实现应用一打开,就可以向右滑动
         mViewPager.setCurrentItem(index);
     }
 
     private class MyOnPageChangeListener implements OnPageChangeListener {
 
         // 开始
         @Override
         public void onPageScrollStateChanged( int arg0) {
         }
 
         // 正在进行时
         @Override
         public void onPageScrolled( int arg0, float arg1, int arg2) {
         }
 
         // 结束
         @Override
         public void onPageSelected( int position) {
             // 当页面滑动结束时,先对页面位置取模
             position = position % imageViewlist.size();
             // 设置textview的文本内容
             imgDes.setText(imageDescription[position]);
             // 将上一个点的可用性设置为false
             layoutPGroup.getChildAt(previousPoint).setEnabled( false );
             // 把当前点的可用性设置为true
             layoutPGroup.getChildAt(position).setEnabled( true );
             // 把当前位置值赋值给previousPoint
             previousPoint = position;
         }
     }
 
     private class MyPagerAdapter extends PagerAdapter {
 
         /**
          * 返回图片总数,Integer.MAX_VALUE的值为 2147483647这个数有21亿,也就是说我们的viewpager
          * 理论上在每次使用应用的时候可以滑动21亿次,当然,实际上是没人要去这么做的,我们这样做是为了实现实现viewpager循环滑动的效果
          * 即当滑动到viewpager的最后一页时,继续滑动就可以回到第一页
          *
          */
         @Override
         public int getCount() {
             return Integer.MAX_VALUE;
         }
 
         @Override
         public boolean isViewFromObject(View arg0, Object arg1) {
             return arg0 == arg1;
         }
 
         // 当某一页滑出去的时候,将其销毁
         @Override
         public void destroyItem(ViewGroup container, int position, Object object) {
             container.removeView(imageViewlist.get(position
                     % imageViewlist.size()));
         }
 
         // 向容器中添加图片,由于我们要实现循环滑动的效果,所以要对position取模
         @Override
         public Object instantiateItem(ViewGroup container, int position) {
             container
                     .addView(imageViewlist.get(position % imageViewlist.size()));
             return imageViewlist.get(position % imageViewlist.size());
         }
     }
 
     // 当activity销毁时,让线程停止
     @Override
     protected void onDestroy() {
         isStop = true ;
         super .onDestroy();
     }
 
}</imageview></imageview></code>

代码中的注释已经说的很详细了,我就不再赘述了。


资源下载链接为: https://pan.quark.cn/s/9648a1f24758 Java JDK(Java Development Kit)是Java编程语言的核心组件,为开发和运行Java程序提供了必要的工具和环境。JDK 8是Oracle公司推出的一个重要版本,它引入了许多新特性和改进,极大地提升了开发效率和代码质量,对开发者来说具有极高的实用价值。 本次提供的“jdk-8u251-macosx-x64.dmg”安装包是专为Mac OS X系统设计的64位版本,其中不仅包含了Java运行环境(JRE),还涵盖了丰富的开发工具,方便用户在Mac平台上进行Java程序的开发与运行。 JDK 8的关键更新和特性如下: Lambda表达式:这是JDK 8的一项重大语法创新,允许开发者使用简洁的匿名函数替代复杂的多行回调代码,从而使代码更加简洁、易读且高效。 方法引用与构造器引用:与Lambda表达式配合使用,可以更直观地引用已有的方法或构造器,进一步减少冗余代码,提升代码的可维护性。 Stream API:这是一个用于处理集合的新API,采用声明式处理方式,使集合操作(如过滤、映射和归约等)更加高效且易于理解。 日期和时间API的改进:JDK 8对日期和时间API进行了重构,引入了java.time包,包含LocalDate、LocalTime和LocalDateTime等类,替代了原有的java.util.Date和java.util.Calendar,使日期和时间的处理更加友好和灵活。 Optional类:为解决null对象导致的空指针异常问题,JDK 8引入了Optional类,它是一个容器对象,可以表示一个值存在或不存在,从而有效避免空指针异常。 接口的默认方法和静态方法:接口现在可以定义默认方法(使用default关键字)和静态方法。默认方法允许在不破坏向后
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值