转载请注明出处:http://blog.csdn.net/qq_26869239/article/details/53378024
经常看到App里面都有广告条这个功能,因为三方框架很多,但是在学习了自定义控件后,就自己突发奇想自己写了一个出来。
觉得要简单简单再简单为好。毕竟是自己写的,觉得用起来还是喜欢一句话为好。
1.先来看看最终效果吧
private void setBanner(String[] bannerUrl) {
if (bannerUrl.length == 0) {
return;
}
if (isClearBannerHandler) {//如果不是第一次,就需要停止自定义里面的Handler
vr_banner.removeHandler();
}
vr_banner.setViewPagerImages(getActivity().getApplicationContext(), bannerUrl);
}
是不是很简单呀,就是一个方法setViewPagerImages,里面传的参数,可以是本地图片,也可以是网络Url地址的一个集合。
接下来来看,具体的实现。
具体的就是添加一个类继承RelativeLayout,然后动态添加ViewPager和RadioButton上去
/**
* 初始化函数 这里只需要初始化一个viewPager出来
*
* @param context 上下文
* @param attrs
* @param defStyleAttr
*/
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
viewPager = addViewPager(context);
//把这个viewPager添加到这个自定义布局上面
addView(viewPager);
// 要进行联动,所以这里要给viewPager添加一个监听器
ViewPagerAndRadioGroupListener listener = new ViewPagerAndRadioGroupListener();
viewPager.addOnPageChangeListener(listener);
}
添加ViewPager的方法很简单,相信大家都会
/**
* 初始化一个ViewPager
*
* @param context 上下文
* @return 写好的一个ViewPager控件
*/
@NonNull
private ViewPager addViewPager(Context context) {
//首先先来一个ViewPager控件
ViewPager viewPager = new ViewPager(context);
//设置一下位置
LayoutParams vParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
viewPager.setLayoutParams(vParams);
//加进布局
return viewPager;
}
然后因为RadioButton个数应该是根据传入的图片个数来决定的,所以我写了一个方法,可以把数据传过来,就是
public void setViewPagerImages(Context context, String[] imagePaths, String[] showWebUrls,OnItemClickListener fetchListener)这个方法
参数说明一下,第一个参数不用说了,第二个参数是网络图片Url的一个地址集合,第三个参数是点击跳转的一个Url集合,第四个参数是一个回调接口,把点击效果调出去,一个图片对应一个网址,或者一个事件,我把点击的位置和地址都回调了出来,至于跳转Activity还是Url就看个人喜好啦。
//自己写一个点击事件的接口
public interface OnItemClickListener {
void onItemClick(int position, String webUrl);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
下面来大概写一下RadioButton的个数添加,根据传入的网址个数来动态添加
/**
* 初始化RadioButton
*
* @param context 上下文
* @return 写好的一个radioGroup控件
*/
private RadioGroup addRadioGroup(Context context) {
//再来一个RadioGroup
RadioGroup radioGroup = new RadioGroup(context);
LayoutParams rgParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//设置位置,在viewPager的下中位置
rgParams.addRule(ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
rgParams.addRule(CENTER_HORIZONTAL, RelativeLayout.TRUE);
radioGroup.setLayoutParams(rgParams);
//设置一下radioGroup的子控件排列顺序
radioGroup.setOrientation(LinearLayout.HORIZONTAL);
//在来三个RadioButton
RadioButton rb = null;
RadioGroup.LayoutParams rbParams;
//这里就是来。添加radioButton
if (str != null) {
for (int i = 0; i < str.length; i++) {
rb = new RadioButton(context);
//添加一个自定义的背景
rb.setButtonDrawable(R.drawable.selector_radiobutton_fill_empty);
//间隔太近了
rbParams = new RadioGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rbParams.setMargins(8, 5, 8, 8);
rb.setLayoutParams(rbParams);
radioGroup.addView(rb);
}
}
if (reStr != null) {
for (int i = 0; i < reStr.length; i++) {
rb = new RadioButton(context);
//添加一个自定义的背景
rb.setButtonDrawable(R.drawable.selector_radiobutton_fill_empty);
//间隔太近了
rbParams = new RadioGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rbParams.setMargins(5, 5, 5, 5);
rb.setLayoutParams(rbParams);
radioGroup.addView(rb);
}
}
return radioGroup;
}
因为博主能力有限,所以封装的时候都写在了一起,O(∩_∩)O哈哈~
然后要让Banner条滚动起来,我用了Handler,但是Handler可能会造成内存泄漏,无意间我在网上看到了一个WeakHandler,有兴趣的童鞋可以去搜搜开,避免内存泄漏的,我就用了这个Handler
//自己滚动起来
//Handler handler = new Handler();
WeakHandler handler = new WeakHandler();
int currentItemId;
Runnable runnable = new Runnable() {
@Override
public void run() {
if (isWebImagePath) {
//发送当前位置
currentItemId = viewPager.getCurrentItem() + 1 % str.length;
} else {
currentItemId = viewPager.getCurrentItem() + 1 % reStr.length;
}
//设置一下
viewPager.setCurrentItem(currentItemId);
handler.postDelayed(runnable, 4000);
}
};
但是后来调用的时候也发现,因为setViewPagerImages这个方法,因为是写在网络请求里面的,当刷新的时候,由于内部的Handler会多次创建,会导致出现一些小问题,所以我又加了一个清除Handler的方法:
**
* 停止线程
*/
public void removeHandler(){
if(handler != null && runnable != null) {
handler.removeCallbacks(runnable);
((RadioButton) (radioGroup.getChildAt(viewPager.getCurrentItem() % str.length))).setChecked(false);
}
}
所以在请求数据的时候,第二次开始的时候判断一下,要清除Handler,给一个boolean值判断即可,清楚以后在调用setViewPagerImages就没有问题了,
/**
* 模拟设置广告条
*/
private void setBanner(String[] bannerUrl) {
if (bannerUrl.length == 0) {
return;
}
if (isClearBannerHandler) {//如果不是第一次,就需要停止自定义里面的Handler
vr_banner.removeHandler();
}
vr_banner.setViewPagerImages(getActivity().getApplicationContext(), bannerUrl);
}
毕竟能力有限,这也是自己动手写的第一个自定义的View,大家-,-有需要的就去下来用吧。
具体用法:
1.添加Viewpager_RadioButton_View.java到自己的项目中,
2.添加
selector_radiobutton_fill_empty,shape_radiobutton_empty,shape_radiobutton_fill三个文件到res/drawable资源下面,
3.gradle里面添加WeakHanlder和Picasso的三方:
compile 'com.squareup.picasso:picasso:2.5.2'
repositories {
maven {
repositories {
url 'https://oss.sonatype.org/content/repositories/releases/'
}
}
}
dependencies {
compile 'com.badoo.mobile:android-weak-handler:1.1'
}
4.最后别忘记开权限啦
<uses-permission android:name="android.permission.INTERNET"/>
。。
5. 然后在xml文件中直接添加这个自定义控件:
<com.jimmy.banner.Viewpager_RadioButton_View
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="150dp"
/>
直接用啦
public class MainActivity extends AppCompatActivity {
private Viewpager_RadioButton_View banner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
banner = (Viewpager_RadioButton_View) findViewById(R.id.banner);
banner.setViewPagerImages(
getApplicationContext(),
new String[]{"http://img5.imgtn.bdimg.com/it/u=2748753796,1780454549&fm=23&gp=0.jpg",
"http://img5.imgtn.bdimg.com/it/u=2748753796,1780454549&fm=23&gp=0.jpg"});
}
}
效果:
最后附上源码地址:
http://download.csdn.net/detail/qq_26869239/9695970