編輯:關於Android編程
在我們下載了一個App第一次進入的時候,或者是已有App更新之後第一次進入時,一般都會有一個引導界面,這個界面用於展示本App的基本功能,或者是更新之後版本的重大改進;效果圖如下:
這裡就簡單的記錄以下這個功能的實現;
1.布局頁面分析
布局代碼如下:
注意:
對於布局文件中Button的Visibility設置為false,不可見.在引導頁的最後一頁的時候,再將其設置為可見.
2.業務邏輯
難點:觀察效果圖注意到底部的小紅點,當引導圖滑動時,底部的小紅點是跟隨著滑動的.
2.1對小紅點隨頁面移動而移動的分析如下:
ViewPager有一個監聽事件: ViewPager.setOnPageChangeListener,
其中有一個重寫的方法是這樣的:
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
其中positionOffset參數是VIewPager中頁面移動的百分比.
這樣我們就可以得到一個思路:
小紅點移動的距離(小紅點的leftMargin值)=兩小紅點間距離*頁面移動百分比(positionOffset)+當前位置的距離
2.2接下來分析兩小紅點之間的距離
從分析圖片中可以看到,兩小紅點之間的距離(mPointDis)=第二個紅點的left值-第一個紅點的left值.
mPointDis = ll_container.getChildAt(1).getLeft() - ll_container.getChildAt(0).getLeft();
注意:
mPointDis 值必須要在View的位置確定了之後才可以得到(View的繪制有如下幾個步驟:measures->layout(確定位置)->draw),所以我們要對小紅點設置監聽,當其位置確定了之後才拿mPointDis值.
//監聽layout方法結束,位置確定好了之後,再計算值
iv_red_point.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//layout方法執行結束的回調
//移除監聽避免重復回調
iv_red_point.getViewTreeObserver().removeOnGlobalLayoutListener(this);
/*計算兩個圓點的距離 第二個圓點的left值-第一個圓點的left值
* measures->layout(確定位置)->draw Acivity的onCreate方法結束後才會走這個流程
* */
mPointDis = ll_container.getChildAt(1).getLeft() - ll_container.getChildAt(0).getLeft();
Log.d("------>" + "計算兩個圓點的距離", mPointDis + "");
}
});
2.3監聽VIewPager的滑動,小紅點隨之而動
小紅點的移動也就是在底部線性布局中的marginLeft值的改變.
由上訴分析得來的公式:
小紅點移動的距離(小紅點的leftMargin值)=兩小紅點間距離*頁面移動百分比(positionOffset)+當前位置的距離
可以得到如下代碼:
int leftMargin = (int) (mPointDis * positionOffset) + position * mPointDis;
然後將leftMargin的值從新設置給小紅點的參數即可:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
iv_red_point.getLayoutParams(); //拿到小紅點的布局參數
layoutParams.leftMargin = leftMargin; //修改小紅點的布局參數
iv_red_point.setLayoutParams(layoutParams); //重新設置小紅點的布局參數
2.4業務邏輯完整代碼
package com.example.lenovo.ruizhiapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.example.lenovo.utils.PrefUtils;
import java.util.ArrayList;
/**
* 新手引導界面
* Created by lenovo on 2016/7/7.
*/
public class GuideActivity extends Activity {
private ViewPager vp_guide;
//引導頁圖片ID數組
private int[] mImageIds = new int[]{R.drawable.guide_1,
R.drawable.guide_2,
R.drawable.guide_3};
//imageView的集合
private ArrayList mImageViewList;
private LinearLayout ll_container;
private ImageView iv_red_point;
private int mPointDis;
private Button btn_start;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_guid);
initViews();//初始化界面控件
initData();//先初始化數據,然後再設置數據
vp_guide.setAdapter(new GuideAdapter());//設置數據
}
private void initViews() {
vp_guide = (ViewPager) findViewById(R.id.vp_guide);
ll_container = (LinearLayout) findViewById(R.id.ll_container);
iv_red_point = (ImageView) findViewById(R.id.iv_red_point);
btn_start = (Button) findViewById(R.id.btn_start);
//對ViewPager頁面滑動的監聽
vp_guide.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override //頁面滑動過程中的回調方法
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
Log.d("------>" + "當前位置:", position + "");
Log.d("------>" + "偏移百分比:", positionOffset + "");
//更新小紅點的距離=移動百分比*兩個原點間的間距+當前位置
int leftMargin = (int) (mPointDis * positionOffset) + position * mPointDis;
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
iv_red_point.getLayoutParams(); //拿到小紅點的布局參數
layoutParams.leftMargin = leftMargin; //修改小紅點的布局參數
iv_red_point.setLayoutParams(layoutParams); //重新設置小紅點的布局參數
}
@Override //某個頁面被選中
public void onPageSelected(int position) {
//最後一個頁面才顯示"開始體驗的按鈕"
if (position==mImageViewList.size()-1){ //靈活代碼
//只在引導頁面的最後一頁顯示按鈕
btn_start.setVisibility(View.VISIBLE);
}else{
//其余引導頁面不顯示按鈕
btn_start.setVisibility(View.INVISIBLE);
}
}
@Override //頁面狀態發生變化 (滑-->不滑)
public void onPageScrollStateChanged(int state) {
}
});
//監聽layout方法結束,位置確定好了之後,再計算值
iv_red_point.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//layout方法執行結束的回調
//移除監聽避免重復回調
iv_red_point.getViewTreeObserver().removeOnGlobalLayoutListener(this);
/*計算兩個圓點的距離 第二個圓點的left值-第一個圓點的left值
* measures->layout(確定位置)->draw Acivity的onCreate方法結束後才會走這個流程
* */
mPointDis = ll_container.getChildAt(1).getLeft() - ll_container.getChildAt(0).getLeft();
Log.d("------>" + "計算兩個圓點的距離", mPointDis + "");
}
});
btn_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(),MainActivity.class));
//表示已經不是第一次進入,跟新SP
PrefUtils.setBoolean(getApplicationContext(),ConstantValues.IS_FIRST_ENTER,false);
//結束引導界面
finish();
}
});
}
//初始化數據
private void initData() {
mImageViewList = new ArrayList();
for (int i = 0; i < mImageIds.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setBackgroundResource(mImageIds[i]);//通過設置背景,可以讓寬高填充布局
mImageViewList.add(imageView);
//初始化底部小圓點
ImageView point = new ImageView(this);
point.setImageResource(R.drawable.shape_point_gray);//設置圖片
//初始化布局參數,寬高包裹內容,父控件是誰就申明誰的布局參數
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
if (i > 0) {
//從第二個點開始設置原點之間的間隔
layoutParams.leftMargin = 10;
}
point.setLayoutParams(layoutParams);//設置布局參數
ll_container.addView(point);//給容器添加原點
}
}
class GuideAdapter extends PagerAdapter {
@Override //返回Item的個數
public int getCount() {
return mImageViewList.size();
}
@Override //固定寫法
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override //初始化Item布局
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = mImageViewList.get(position);
container.addView(imageView);
return imageView;
}
@Override //銷毀Item
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
}
設置標題欄背景1> 准備背景圖片: background_pix.png注:用背景圖片比用顏色好處,可以讓背景看起來有凹凸感.2> drawable文件夾下放
知識點:第一:實現首頁的3個tab,讓tab與viewpager實現聯動第二:輪播圖的無限次自動循環滾動。先看效果圖:項目結構圖:我們在捋順一下邏輯: 每一個側拉頁的it
ListView的下拉刷新很常見,很多開源的框架都能做到這個效果,當然也可以自己去實現。本篇案例是基於xlistview的。布局:<RelativeLayout x
這是翻譯官方的文檔,英語好的可以直接去官方文檔查看,英語不好,大家就將就看吧,算是我翻譯的第一篇技術文章,因為是個英語渣,技術也渣,所以最近在學英語,就嘗試著自己來翻譯