首先ViewPager是android扩展包V4包中的类,是可以让用户实现左右滚动的容器类。先看官方文档的描叙:
Layout manager that allows the user to flip left and right through pages of data. You supply an implementation of a PagerAdapter to generate the pages that the view shows
翻译:布局管理器,允许用户通过页面翻转左右的数据。你提供一个实现PagerAdapter生成视图显示的页面
可知ViewPager跟listView一样,也是需要一个适配器去填充数据,也就是PagerAdapter。
通过文档可知以下信息:
A:ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的view类。
B: 需要用PagerAdapter去填充数据
C:需要引入v4包:android.support.v4.view.ViewPager
广告轮播的例子:要求:能实现自动轮播,可以伪无限左右滑动。
先看布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="220dp" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="220dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:background="#66000000"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="5dp" >
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="天王盖地虎,宝塔镇河妖 "
android:textColor="@android:color/white" />
<LinearLayout
android:id="@+id/ll_point"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="horizontal" >
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
可以看出引用必须是完整的包名,而且android.support.v4.view.ViewPager下能够放置子View
activity程序
package com.itheima.pagerview;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnPageChangeListener {
private ViewPager viewpager;
private int[] imageResIds;
private List<ImageView> imageViewList;
private LinearLayout ll_point_container;
private TextView tv_desc;
private String[] contentDescs;
private int previousSelectedPosition = 0;
private boolean isRunning;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化布局View
initViews();
// Modele 数据
initData();
// Controller 控制器
initAdapter();
// 开启轮播
new Thread() {
public void run() {
isRunning = true;
while (isRunning) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 2秒后跳到下一位 计时器
runOnUiThread(new Runnable() {
@Override
public void run() {
viewpager.setCurrentItem(viewpager.getCurrentItem()+1);
}
});
}
};
}.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
isRunning=false;
}
private void initAdapter() {
// 先设置0号位的数据
ll_point_container.getChildAt(0).setEnabled(true);
tv_desc.setText(contentDescs[0]);
// previousSelectedPosition = 0;
// 设置适配器
viewpager.setAdapter(new MyAdapter());
// 默认设置到中间的某个位置
int pos = Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2 % imageViewList.size());
// 2147483647 / 2 = 1073741823 - (1073741823 % 5)
viewpager.setCurrentItem(5000000); // 设置到某个位置,设置为5的倍数
}
/**
* @author hujin PagerAdapter 为viewpager填充数据
*/
class MyAdapter extends PagerAdapter {
private ImageView imageView;
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
// 3,指定复用的判断逻辑 固定写法
@Override
public boolean isViewFromObject(View view, Object object) {
// 当划到新的条目, 又返回来, view是否可以被复用.
// 返回判断规则
return view == object;
}
// 1,返回要显示的条目内容
@Override
public Object instantiateItem(ViewGroup container, int position) {
// container 容器:ViewPager
// position 当前显示条目的为哦在
int newPosition = position % imageViewList.size();
imageView = imageViewList.get(newPosition);
// a,把view添加到container里面
container.addView(imageView);
// b,把view对象返回给框架,适配器
return imageView;
}
// 2,销毁条目
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// object 要销毁的对象
container.removeView((View) object);
}
}
private void initData() {
// 文本描述
contentDescs = new String[] { "巩俐不低俗,我就不能低俗", "扑树又回来啦!再唱经典老歌引万人大合唱", "揭秘北京电影如何升级", "乐视网TV版大派送", "热血屌丝的反杀" };
// 图片资源id数组
imageResIds = new int[] { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e };
imageViewList = new ArrayList<ImageView>();
ImageView imageView;
View pointView;
LayoutParams layoutParams;
for (int i = 0; i < imageResIds.length; i++) {
imageView = new ImageView(this);
imageView.setBackgroundResource(imageResIds[i]);
imageViewList.add(imageView);
// 加小白点, 指示器
pointView = new View(this);
pointView.setBackgroundResource(R.drawable.selector_bg_point);
layoutParams = new LinearLayout.LayoutParams(10, 10);
if (i != 0) {
layoutParams.leftMargin = 15;
}
pointView.setEnabled(false);
ll_point_container.addView(pointView, layoutParams);
}
}
private void initViews() {
ll_point_container = (LinearLayout) findViewById(R.id.ll_point);
viewpager = (ViewPager) findViewById(R.id.viewpager);
tv_desc = (TextView) findViewById(R.id.tv_desc);
<span style="white-space:pre"> </span>viewpager.setOffscreenPageLimit(1);//左右各保留几个对象
viewpager.setOnPageChangeListener(this);// 设置页面更新监听
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// 滚动时调用
}
@Override
public void onPageSelected(int position) {
// 新的条目被选中时调用
System.out.println("onPageSelected: " + position);
int newPosition = position % imageViewList.size();
// 设置文本
tv_desc.setText(contentDescs[newPosition]);
// for (int i = 0; i < ll_point_container.getChildCount(); i++) {
// View childAt = ll_point_container.getChildAt(position);
// childAt.setEnabled(position == i);
// }
// 把之前的禁用, 把最新的启用, 更新指示器
ll_point_container.getChildAt(previousSelectedPosition).setEnabled(false);
ll_point_container.getChildAt(newPosition).setEnabled(true);
// 记录之前的位置
previousSelectedPosition = newPosition;
}
@Override
public void onPageScrollStateChanged(int state) {
// 滚动状态变化时调用
}
}
分析:
要设置左右各保留几个对象:
viewpager.setOffscreenPageLimit(1);//左右各保留几个对象
1:代表左右各有1个对象,加上自身 一共总共保留3个对象。比如每当向右滑动的新的页面加载出来,会自动移位置,原来左边的被销毁、原来正在显示的会变成新的左边对象,原理右边对象会变成正在显示的,新的右边对象会被预加载出来为右对象。逻辑很简单,不多描叙。显示这么默认值为1。一般取默认值就行。
设置adpter的:
private void initAdapter() {
// 先设置0号位的数据
ll_point_container.getChildAt(0).setEnabled(true);
tv_desc.setText(contentDescs[0]);
// previousSelectedPosition = 0;
// 设置适配器
viewpager.setAdapter(new MyAdapter());
// 默认设置到中间的某个位置
int pos = Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2 % imageViewList.size());
// 2147483647 / 2 = 1073741823 - (1073741823 % 5)
viewpager.setCurrentItem(5000000); // 设置到某个位置,设置为5的倍数
}
这里要首先给对0号位置(进入页面第一个显示的滚动条)进行设定数据,
这里要注意的是:要实现广告的左右滑动,所有要让0位置的Pager能像左滑动,所以要把0位置设置在总position个数的中间数,而且这个数能整除pager的个数。这样才能保证设置在0位置。
例子:我们这里设置ViewPager显示为5个Pager页面,那么第5个条目position要显示,所以处理后要设置为5/5---余数为 0,显示在第0个页面,第6个条目为:6/5---余数为 1,显示在第1个页面。
适配器的类:
class MyAdapter extends PagerAdapter {
private ImageView imageView;
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
// 3,指定复用的判断逻辑 固定写法
@Override
public boolean isViewFromObject(View view, Object object) {
// 当划到新的条目, 又返回来, view是否可以被复用.
// 返回判断规则
return view == object;
}
// 1,返回要显示的条目内容
@Override
public Object instantiateItem(ViewGroup container, int position) {
// container 容器:ViewPager
// position 当前显示条目的为哦在
int newPosition = position % imageViewList.size();
imageView = imageViewList.get(newPosition);
// a,把view添加到container里面
container.addView(imageView);
// b,把view对象返回给框架,适配器
return imageView;
}
// 2,销毁条目
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// object 要销毁的对象
container.removeView((View) object);
}
}
按照实现要求,能无限滑动,所以这里设置的条目数为int类型的最大值:Integer.MAX_VALUE:2147483647
你需要滑动几十年才能滑动终点,而且还要保持设备不能关机或者重新加载。这里的伪无限循环效果基本可以看出是无效循环滑动。同样要求对pager页面个数的余数。
这里的4个方法写法很固定,跟listview的adapter差不多。0、设置条目个数。1,返回要显示的内容。2、销毁条目:根据设定的预保留对象。3、判断是否复用。
设置的滑动监听:实现接口:
public class MainActivity extends Activity implements OnPageChangeListener
接口的方法;
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// 滚动时调用
}
@Override
public void onPageSelected(int position) {
// 新的条目被选中时调用
System.out.println("onPageSelected: " + position);
int newPosition = position % imageViewList.size();
// 设置文本
tv_desc.setText(contentDescs[newPosition]);
// for (int i = 0; i < ll_point_container.getChildCount(); i++) {
// View childAt = ll_point_container.getChildAt(position);
// childAt.setEnabled(position == i);
// }
// 把之前的禁用, 把最新的启用, 更新指示器
ll_point_container.getChildAt(previousSelectedPosition).setEnabled(false);
ll_point_container.getChildAt(newPosition).setEnabled(true);
// 记录之前的位置
previousSelectedPosition = newPosition;
}
@Override
public void onPageScrollStateChanged(int state) {
// 滚动状态变化时调用
}
监听就是做数据的刷新。
自动轮播的代码:定时为耗时操作,要交给子线程操作,设定一个睡眠时间之后再设置当前条目+1
// 开启轮播
new Thread() {
public void run() {
isRunning = true;
while (isRunning) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 2秒后跳到下一位 计时器
runOnUiThread(new Runnable() {
@Override
public void run() {
viewpager.setCurrentItem(viewpager.getCurrentItem()+1);
}
});
}
};
}.start();
总结:要了解PagerAdapter适配器的用法,很固定。
更重要的是弄清楚怎样实现无限滚动。
android 中应用的 : 清理数据 和缓冲的区别:
清理数据:是指删除此应用的所有数据。包括:所有的文件、设置、账号、数据库。也包括运行时产生的图片,视频等
下次进入程序就和第一次进入程序时一样。
缓冲:聊天记录、朋友圈缓存的用户头像、图片、文字等信息都会被清除掉。
是是程序运行时的临时存储空间,它可以存放从网络下载的临时图片,请求的数据。就是软件使用时所建立的
一定量的需拟内存,以方便其起动与运行的稳定和速度。下次进入的时候,不用再去网上请求数据,加快了手机运行
速度。
简单的打包:
1、反击点击要打包的项目--->Android Tools -->Export Signed Application Package
2、出现下面界面,确认项目,点击next就行
3、出现以下界面。
Use existing keystore: 使用以前生产出来的旧签名文件
Create new keystore: 创建新的签名文件
地址:一般为工作区间项目下的根目录----保存好。
这里为新建一个新的签名文件。
这里要创建密码和确认密码
4、选好路径和确认密码后,点击next后出现以下
这里先只填部分就行了:
Password 密码
Confirm 确认密码
Validity 有效时长
City or Locality 城市或者地区
5、点击next后为:选择apk存放地址,点击完成就行了