Android ViewPager制作新手導(dǎo)航頁(yè)(動(dòng)態(tài)加載)
我們來(lái)講個(gè)老生常談的話題,估計(jì)大家都用過(guò)的—>ViewPager,用它來(lái)做新手導(dǎo)航頁(yè)面,雖然這次也是講這個(gè),但是和以往的用法可能有些不同,大家都看到標(biāo)題進(jìn)來(lái)的,應(yīng)該知道的是:動(dòng)態(tài)加載指示器。
什么叫動(dòng)態(tài)加載呢,是不是感覺(jué)很高大上呢,其實(shí)呢就是動(dòng)態(tài)的去加載指示器的數(shù)量的,而不是在布局文件中寫(xiě)死。希望看了這篇文章大家對(duì)ViewPager有新的認(rèn)識(shí)。

看到這個(gè)效果大家應(yīng)該都很不屑吧,今天講這個(gè)就是為了讓大家有新的認(rèn)識(shí)。好了,好好聽(tīng),開(kāi)始了。
這個(gè)動(dòng)態(tài)加載就是為了動(dòng)態(tài)的加載下面的灰色圓點(diǎn)指示器和紅色圓點(diǎn)指示器,大家有沒(méi)有注意到當(dāng)我滑動(dòng)的時(shí)候(即切換頁(yè)面的時(shí)候)紅色圓點(diǎn)會(huì)跟著移動(dòng)。沒(méi)錯(cuò)。
第一步:
在布局文件中添加ViewPager,并添加灰色圓點(diǎn)和紅色圓點(diǎn)的布局,先來(lái)想想都用什么布局呢,首先三個(gè)灰色圓點(diǎn)可以用線性布局,一個(gè)紅色圓點(diǎn)可以采用相對(duì)布局(原因:其實(shí)紅色圓點(diǎn)就是覆蓋在灰色圓點(diǎn)上)
<RelativeLayout
android:id="@+id/rl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="30dp" >
<!--灰色圓點(diǎn)的布局-->
<LinearLayout
android:id="@+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
</RelativeLayout>
第二步:
在onCreate方法中聲明ViewPager和灰色圓點(diǎn)和紅色圓點(diǎn)布局的示例(原因:因?yàn)槲覀冃枰獎(jiǎng)討B(tài)加載圓點(diǎn)),并為ViewPager添加適配器和監(jiān)聽(tīng)器。
//ViwePager
private ViewPager viewPager;
//存放三個(gè)灰色圓點(diǎn)的線性布局
private LinearLayout ll;
//用來(lái)存放紅色圓點(diǎn)和灰色圓點(diǎn)的相對(duì)布局
private RelativeLayout rl;
//初始化組件
private void initView() {
viewPager = (ViewPager) findViewById(R.id.viewPager);
imageViews = new ArrayList<ImageView>();
ll = (LinearLayout) findViewById(R.id.ll);
rl = (RelativeLayout) findViewById(R.id.rl);
btn = (Button) findViewById(R.id.btn);
//為ViewPager添加適配器
viewPager.setAdapter(new MyAdapter());
viewPager.setOnPageChangeListener();
第三步:
將三個(gè)圖片加到ViewPager的適配器中。
注:為了在滑動(dòng)的時(shí)候不重復(fù)創(chuàng)建圖片實(shí)例,所以我們可以先將需要加載的資源的放在一個(gè)集合中,當(dāng)每次滑動(dòng)需要加載的時(shí)候就從集合中取出即可,這樣節(jié)省了系統(tǒng)資源。
//導(dǎo)航頁(yè)資源
private int[] images = new int[]{
R.drawable.guide_1,
R.drawable.guide_2,
R.drawable.guide_3,
};
//用來(lái)存放導(dǎo)航圖片實(shí)例(保證唯一性,滑動(dòng)的時(shí)候不重復(fù)創(chuàng)建)
private List<ImageView> imageViews;
//初始化導(dǎo)航頁(yè)面
for (int i = 0; i < images.length; i++) {
ImageView iv = new ImageView(MainActivity.this);
iv.setImageResource(images[i]);
imageViews.add(iv);
}
//PagerAdapter有四個(gè)方法
class MyAdapter extends PagerAdapter {
//返回導(dǎo)航頁(yè)的個(gè)數(shù)
@Override
public int getCount() {
return images.length;
}
//判斷是否由對(duì)象生成
@Override
public boolean isViewFromObject(View view,Object object) {
return view == object;
}
//加載頁(yè)面
//ViewGroup:父控件指ViewPager
//position:當(dāng)前子控件在父控件中的位置
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView iv = imageViews.get(position);
container.addView(iv);
return iv;
}
//移除頁(yè)面
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
第四步:
重要的部分來(lái)了,這一步是動(dòng)態(tài)的將灰色圓點(diǎn)和紅色圓點(diǎn)添加進(jìn)來(lái),并讓紅色圓點(diǎn)隨著滑動(dòng)也跟著一起滑動(dòng)。
首先動(dòng)態(tài)的添加灰色圓點(diǎn)和紅色圓點(diǎn):
for (int i = 0; i < images.length; i++) {
ImageView iv = new ImageView(MainActivity.this);
iv.setImageResource(images[i]);
imageViews.add(iv);
//動(dòng)態(tài)加載灰色圓點(diǎn)
ImageView gray_Iv = new ImageView(this);
gray_Iv.setImageResource(R.drawable.grar_circle);
LinearLayout.LayoutParams layoutParams =
new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
//從第二個(gè)開(kāi)始有邊距
if (i > 0) {
layoutParams.leftMargin = 20; //注意單位是px
}
gray_Iv.setLayoutParams(layoutParams);
ll.addView(gray_Iv);
}
//添加紅色圓點(diǎn)
red_Iv = new ImageView(this);
red_Iv.setImageResource(R.drawable.red_circle);
rl.addView(red_Iv);
注:灰色圓點(diǎn)是從第二個(gè)開(kāi)始有左邊距的,為組件動(dòng)態(tài)的設(shè)置邊距的話使用布局的LayoutParams(衣服),記住三個(gè)灰色圓點(diǎn)使用的是哪個(gè)布局就采用那種布局的LayoutParams來(lái)進(jìn)行設(shè)置。
下面就是讓紅色圓點(diǎn)隨著ViewPager滑動(dòng)也跟著一起滑動(dòng):
//任何一個(gè)組件都可以得到視圖樹(shù)
red_Iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
//視圖完成繪制的時(shí)候調(diào)用
@Override
public void onGlobalLayout() {
left = ll.getChildAt(1).getLeft() - ll.getChildAt(0).getLeft();
System.out.println(left);
//移除視圖樹(shù)的監(jiān)聽(tīng)
red_Iv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
//導(dǎo)航頁(yè)滑動(dòng)的時(shí)候調(diào)用
//positionOffset:滑動(dòng)的百分比([0,1})
@Override
public void onPageScrolled(int position, float positionOffset, int arg2) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) red_Iv.getLayoutParams();
layoutParams.leftMargin = (int) (left * positionOffset + position * left);
red_Iv.setLayoutParams(layoutParams);
}
注:這里需要明白一個(gè)概念–>視圖樹(shù),為什么要明白這個(gè)呢,因?yàn)槲覀兪莿?dòng)態(tài)的將灰色圓點(diǎn)添加進(jìn)去,不知道這個(gè)視圖什么才能繪制好,所以需要監(jiān)聽(tīng)到整個(gè)視圖的繪制狀態(tài),任何一個(gè)組件都可以拿到視圖樹(shù),對(duì)視圖樹(shù)的繪制進(jìn)行監(jiān)聽(tīng)。這樣就可以得到灰色圓點(diǎn)之間的距離,大家又會(huì)問(wèn)一開(kāi)始添加灰色圓點(diǎn)的時(shí)候不是設(shè)置了左邊距嗎???是的,但是這個(gè)單位是px,而現(xiàn)在是dp不能直接設(shè)置。
灰色圓點(diǎn)之間的距離:

left = ll.getChildAt(1).getLeft() - ll.getChildAt(0).getLeft();
public void onPageScrolled(int position, float positionOffset, int arg2)中參數(shù)positionOffset指滑動(dòng)的百分比(范圍[0-1))
現(xiàn)在就可以知道紅色圓點(diǎn)需要滑動(dòng)多少了。
//導(dǎo)航頁(yè)滑動(dòng)的時(shí)候調(diào)用
//positionOffset:滑動(dòng)的百分比([0,1))
@Override
public void onPageScrolled(int position, float positionOffset, int arg2) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) red_Iv.getLayoutParams();
layoutParams.leftMargin = (int) (left * positionOffset + position * left);
red_Iv.setLayoutParams(layoutParams);
}
第五步:
新手導(dǎo)航頁(yè),一般移動(dòng)到最后一頁(yè)的時(shí)候會(huì)有個(gè)按鈕跳到主界面。這個(gè)只需要在導(dǎo)航頁(yè)被選擇的時(shí)候設(shè)置一下即可
//導(dǎo)航頁(yè)被選擇的時(shí)候調(diào)用
@Override
public void onPageSelected(int position) {
//滑動(dòng)到最后一頁(yè),顯示按鈕
if (position == images.length - 1) {
btn.setVisibility(View.VISIBLE);
//不是最后一頁(yè),不顯示按鈕
}else {
btn.setVisibility(View.GONE);
}
}
核心代碼:
布局文件:
<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="com.example.viewpager.MainActivity" >
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v4.view.ViewPager>
<RelativeLayout
android:id="@+id/rl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="30dp" >
<!--灰色圓點(diǎn)的布局-->
<LinearLayout
android:id="@+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
</RelativeLayout>
<Button
android:layout_width="wrap_content"
android:id="@+id/btn"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="50dp"
android:layout_height="wrap_content"
android:text="體驗(yàn)"
android:visibility="gone"
/>
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity {
//ViwePager
private ViewPager viewPager;
private Button btn;
//導(dǎo)航頁(yè)資源
private int[] images = new int[]{
R.drawable.guide_1,
R.drawable.guide_2,
R.drawable.guide_3,
};
//圓點(diǎn)與圓點(diǎn)之間的邊距
private int left;
//用來(lái)存放導(dǎo)航圖片實(shí)例(保證唯一性,滑動(dòng)的時(shí)候不重復(fù)創(chuàng)建)
private List<ImageView> imageViews;
//存放三個(gè)灰色圓點(diǎn)的線性布局
private LinearLayout ll;
//用來(lái)存放紅色圓點(diǎn)和灰色圓點(diǎn)的相對(duì)布局
private RelativeLayout rl;
//紅色圓點(diǎn)ImageView
private ImageView red_Iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//初始化導(dǎo)航頁(yè)面和灰色圓點(diǎn)
for (int i = 0; i < images.length; i++) {
ImageView iv = new ImageView(MainActivity.this);
iv.setImageResource(images[i]);
imageViews.add(iv);
//動(dòng)態(tài)加載灰色圓點(diǎn)
ImageView gray_Iv = new ImageView(this);
gray_Iv.setImageResource(R.drawable.grar_circle);
LinearLayout.LayoutParams layoutParams =
new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
//從第二個(gè)開(kāi)始有邊距
if (i > 0) {
layoutParams.leftMargin = 20; //注意單位是px
}
gray_Iv.setLayoutParams(layoutParams);
ll.addView(gray_Iv);
}
red_Iv = new ImageView(this);
red_Iv.setImageResource(R.drawable.red_circle);
rl.addView(red_Iv);
//任何一個(gè)組件都可以得到視圖樹(shù)
red_Iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
//視圖完成繪制的時(shí)候調(diào)用
@Override
public void onGlobalLayout() {
left = ll.getChildAt(1).getLeft() - ll.getChildAt(0).getLeft();
System.out.println(left);
//移除視圖樹(shù)的監(jiān)聽(tīng)
red_Iv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
//為ViewPager添加適配器
viewPager.setAdapter(new MyAdapter());
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
//導(dǎo)航頁(yè)被選擇的時(shí)候調(diào)用
@Override
public void onPageSelected(int position) {
if (position == images.length - 1) {
btn.setVisibility(View.VISIBLE);
}else {
btn.setVisibility(View.GONE);
}
}
//導(dǎo)航頁(yè)滑動(dòng)的時(shí)候調(diào)用
//positionOffset:滑動(dòng)的百分比([0,1})
@Override
public void onPageScrolled(int position, float positionOffset, int arg2) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) red_Iv.getLayoutParams();
layoutParams.leftMargin = (int) (left * positionOffset + position * left);
red_Iv.setLayoutParams(layoutParams);
}
//導(dǎo)航頁(yè)滑動(dòng)的狀態(tài)改變的時(shí)候調(diào)用
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
//初始化組件
private void initView() {
viewPager = (ViewPager) findViewById(R.id.viewPager);
imageViews = new ArrayList<ImageView>();
ll = (LinearLayout) findViewById(R.id.ll);
rl = (RelativeLayout) findViewById(R.id.rl);
btn = (Button) findViewById(R.id.btn);
}
//PagerAdapter有四個(gè)方法
class MyAdapter extends PagerAdapter {
//返回導(dǎo)航頁(yè)的個(gè)數(shù)
@Override
public int getCount() {
return images.length;
}
//判斷是否由對(duì)象生成
@Override
public boolean isViewFromObject(View view,Object object) {
return view == object;
}
//加載頁(yè)面
//ViewGroup:父控件指ViewPager
//position:當(dāng)前子控件在父控件中的位置
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView iv = imageViews.get(position);
container.addView(iv);
return iv;
}
//移除頁(yè)面
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
}
大家趕緊試試吧。會(huì)有不同的認(rèn)識(shí)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)Android軟件編程有所幫助。
相關(guān)文章
Android 中使用ExpandableListView 實(shí)現(xiàn)分組的實(shí)例
這篇文章主要介紹了Android 中使用ExpandableListView 實(shí)現(xiàn)分組的實(shí)例的相關(guān)資料,這里提供實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-12-12
Android 兩個(gè)ViewPager的聯(lián)動(dòng)效果的實(shí)現(xiàn)
這篇文章主要介紹了Android 兩個(gè)ViewPager的聯(lián)動(dòng)效果的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
Android序列化實(shí)現(xiàn)接口Serializable與Parcelable詳解
我們使用 Intent 傳遞數(shù)據(jù)的時(shí)候,putExtra() 所支持的數(shù)據(jù)類型事有限的,當(dāng)需要傳遞自定義對(duì)象的時(shí)候就需要序列化。Serializable更簡(jiǎn)單但是會(huì)把整個(gè)對(duì)象進(jìn)行序列化因此效率比Parcelable低一些2022-12-12
Android利用RecyclerView編寫(xiě)聊天界面
這篇文章主要為大家詳細(xì)介紹了Android利用RecyclerView編寫(xiě)聊天界面,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Android 側(cè)滑抽屜菜單的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 側(cè)滑抽屜菜單的實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03

