本次的目标是用轮播图实现app中植入广告
最终实现效果
就是最上面这一部分啦
下面丑不拉叽的recyclerview请忽视,还有我自己定义的更加丑不拉叽的groupview导航栏(因为都是自己ps的图标,所以真的奇丑无比)
需要用到的是Viewpager
先在布局xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="200dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="8dp"/>
<LinearLayout
android:weightSum="10"
android:background="#33000000"
android:orientation="horizontal"
android:layout_gravity="bottom"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="35dip">
<TextView
android:layout_weight="8"
android:id="@+id/adv_pager_title"
android:paddingLeft="8dip"
android:gravity="center_vertical"
android:textColor="@color/fragment_4"
android:layout_width="0dp"
android:layout_height="35dip"/>
<!--用来动态添加轮播小点-->
<LinearLayout
android:id="@+id/lineLayout_dot"
android:layout_weight="2"
android:gravity="center|right"
android:layout_marginRight="5dp"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:orientation="horizontal"
android:layout_width="0dp"
android:layout_height="match_parent">
<View
android:id="@+id/small_point_1"
android:layout_weight="0.25"
android:layout_width="0dp"
android:layout_height="18dp"
android:background="@drawable/small_point"/>
<View
android:id="@+id/small_point_2"
android:layout_weight="0.25"
android:layout_width="0dp"
android:layout_height="18dp"
android:background="@drawable/small_point"/>
<View
android:id="@+id/small_point_3"
android:layout_weight="0.25"
android:layout_width="0dp"
android:layout_height="18dp"
android:background="@drawable/small_point"/>
<View
android:id="@+id/small_point_4"
android:layout_weight="0.25"
android:layout_width="0dp"
android:layout_height="18dp"
android:background="@drawable/small_point"/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
那四个view是用来添加四个小圆点的
下面是小圆点的资源绘制
<?xml version="1.0" encoding="utf-8"?>
<!--vector 矢量图-->
<vector
android:height="5dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="5dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<!--
android:viewportHeight="24.0"
android:viewportWidth="24.0" 定义画布宽高
android:fillColor="#fff" 填充颜色
-->
<path android:fillColor="#fff"
android:pathData="M12,12 m-8,0a8,8 0,1 1 16,0 a8,8 0,1 1,-16 0"
/>
</vector>
<!-- 基本语法
M:move to 移动绘制点,作用相当于把画笔落在哪一点。
L:line to 直线,就是一条直线,注意,只是直线,直线是没有宽度的,所以你什么也看不到。
android:strokeColor="#333330" android:strokeWidth="10" 设置颜色和线宽
Z:close 闭合,嗯,就是把图封闭起来。
C:cubic bezier 三次贝塞尔曲线
Q:quatratic bezier 二次贝塞尔曲线
A:ellipse 圆弧-->
<!-- 命令
M (x y) 把画笔移动到x,y,要准备在这个地方画图了。
L (x y) 直线连到x,y,还有简化命令H(x) 水平连接、V(y)垂直连接。
Z,没有参数,连接起点和终点
C(x1 y1 x2 y2 x y),控制点(x1,y1)( x2,y2),终点x,y 。
Q(x1 y1 x y),控制点(x1,y1),终点x,y
A(rx ry x-axis-rotation large-arc-flag sweep-flag x y)
rx ry 椭圆半径
x-axis-rotation x轴旋转角度
large-arc-flag 为0时表示取小弧度,1时取大弧度 (舍取的时候,是要长的还是短的)
sweep-flag 0取逆时针方向,1取顺时针方向
例:
android:pathData=" M50,50 a10,5 90,1 0 1,0"
M50,50 : 点(50,50)落笔
a10,5: x轴半径10,y轴半径5画一个椭圆
90 X轴旋转90度
1: 取大弧度
0: 逆时针取弧度
1,0: (51,50)为终点
-->
这是一个画矢量图的方法
同样的如法炮制再来个蓝色的圆
准备每一个page的布局界面
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/txt_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.constraint.ConstraintLayout>
这里我放了个Textview
正式开工
既然放广告那就新建一个Advertisement类
public class Advertisement {
private String mData;
private String mTitle;
public Advertisement(String data,String title){
mData = data;
mTitle = title;
}
public String getData() {
return mData;
}
public void setData(String mData) {
this.mData = mData;
}
public String getTitle() {
return mTitle;
}
public void setTitle(String mTitle) {
this.mTitle = mTitle;
}
}
敢敢单单两个变量,一个做广告文本,一个做广告标题,文本打算下次替换成图片。
新建一个类或者内部类
class ViewPagerAdapter extends PagerAdapter {
List<View> smallPoints;
List<Advertisement> mData;
Context mContext;
public ViewPagerAdapter(List<View> smallPoints,List<Advertisement> mData, Context context) {
this.smallPoints = smallPoints;
this.mContext = context;
this.mData = mData;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public View instantiateItem(ViewGroup parent, int position) {
View v = View.inflate(mContext, R.layout.item_fragment_1_view_pager, null);
TextView txt = (TextView)v.findViewById(R.id.txt_viewpager) ;
txt.setText(mAdvertisement.get(position).getData());
parent.addView(v);
return v;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
}
重写这几个方法,然后在instantiateItem()方法里实例化每个page的布局,每一次滑动page都会调用这个方法,据说Viewpager会根据你滑动的方向预先加载下一个page,暂时还没深究这个,小白嘛,先掌握使用方法嘻嘻。
初始化数据、控件,并初始化第一个page
class XXX{
private ViewPager mViewPager;
//存放广告
private List<Advertisement> mAdvertisement;
//存放实例化后的小点
private List<View> mSmallPointViews;
private TextView txt_title;
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_1, container, false);
initPoint(v);
initAdvertisement();
//实例化Viewpager
mViewPager = (ViewPager) v.findViewById(R.id.viewPager);
//设置Adapter
mViewPager.setAdapter(new ViewPagerAdapter(mSmallPointViews,mAdvertisement, getContext()));
//初始化第一个page的标题、初始化第一个圆形的颜色为蓝色
mSmallPointViews.get(0).setBackgroundResource(R.drawable.small_point_blue);
txt_title.setText(mAdvertisement.get(0).getTitle());
//设置监听器
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
//page被选中时的方法,
@Override
public void onPageSelected(int position) {
//当前页面对应的小圆形变为蓝色,其他的变为白色
for(int i = 0;i < mAdvertisement.size();i++) {
if(position == i) {
mSmallPointViews.get(i).setBackgroundResource(R.drawable.small_point_blue);
}else {
mSmallPointViews.get(i).setBackgroundResource(R.drawable.small_point);
}
}
//根据position设置对应的title
txt_title.setText(mAdvertisement.get(position).getTitle());
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
return v;
}
}
private void initPoint(View v){
mSmallPointViews = new ArrayList<>();
mSmallPointViews.add((View)v.findViewById(R.id.small_point_1));
mSmallPointViews.add((View)v.findViewById(R.id.small_point_2));
mSmallPointViews.add((View)v.findViewById(R.id.small_point_3));
mSmallPointViews.add((View)v.findViewById(R.id.small_point_4));
}
private void initAdvertisement(){
mAdvertisement = new ArrayList<>();
mAdvertisement.add(new Advertisement("这是广告一的图片","这是广告一的标题"));
mAdvertisement.add(new Advertisement("这是广告二的图片","这是广告二的标题"));
mAdvertisement.add(new Advertisement("这是广告三的图片","这是广告三的标题"));
mAdvertisement.add(new Advertisement("这是广告四的图片","这是广告四的标题"));
}
运行!
虽然是很简单的一个练手Viewpager,但是也遇到了不少问题,比如一开始把加载每个poge的标题和内容都放在了Adapter内部类的instantiateItem()方法里,导致一直报空指针异常,然后日志显示在txt——title.setText()的时候加载的永远是下一个page的title,最后查了点资料,解决办法是
向ViewPager中的控件添加数据时在instantiateItem()中添加,在此处ViewPager只承载了一个一个TextView控件,填满了布局
向ViewPager外面的控件添加数据时,在onPageSelected()中添加数据,并要对数据进行第一个数据的手动添加
感悟
大致今天收获这么多吧,感觉一个人自学安卓真的好难啊,还是要细细的理解代码,一点点读,等熟练使用了以后再去深究源码,先会用再说2333,还有其他Viewpager的很多知识没学,先暂时满足需求了,等有空再回来充实一下~~