溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Android應用中添加一個歡迎界面

發(fā)布時間:2020-11-27 16:40:12 來源:億速云 閱讀:100 作者:Leah 欄目:移動開發(fā)

這篇文章給大家介紹怎么在Android應用中添加一個歡迎界面,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

main_activity.xml文件代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:background="@color/white"
 android:orientation="vertical" >
<com.qianmo.xiaohongshuwelcome.parallaxpager.ParallaxContainer
 android:id="@+id/parallax_container"
 android:layout_width="match_parent"
 android:layout_height="match_parent"/>
 <ImageView
 android:id="@+id/iv_man"
 android:layout_width="67dp"
 android:layout_height="202dp"
 android:layout_alignParentBottom="true"
 android:layout_centerHorizontal="true"
 android:layout_marginBottom="10dp"
android:background="@drawable/intro_item_manrun_1"
 android:visibility="visible" />
</RelativeLayout>

可以看到我們主界面的布局文件主要是兩個控件,一個是包含上面小人行走效果的ImageView,然后是一個自定義ParallaxContainer控件,這個自定義控件的具體是什么我們先不要管,后面再和大家來慢慢解釋

第二步:看一下我們主界面的MainActivity的代碼

MainActivity.java

package com.qianmo.xiaohongshuwelcome;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import com.qianmo.xiaohongshuwelcome.parallaxpager.ParallaxContainer;
/**
 * @author zhongdaxia 2014-12-15
 */
public class MainActivity extends Activity {
 ImageView iv_man;
 ImageView rl_weibo;
 ParallaxContainer parallaxContainer;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 //獲取當前窗體
 final Window window = getWindow();
 window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
 setContentView(R.layout.activity_main);
 /**
 * 動畫支持11以上sdk,11以下默認不顯示動畫
 * 若需要支持11以下動畫,也可導入https://github.com/JakeWharton/NineOldAndroids
 */
 if (android.os.Build.VERSION.SDK_INT > 10) {
 iv_man = (ImageView) findViewById(R.id.iv_man);
 parallaxContainer = (ParallaxContainer) findViewById(R.id.parallax_container);
 if (parallaxContainer != null) {
 parallaxContainer.setImage(iv_man);
 parallaxContainer.setLooping(false);
 iv_man.setVisibility(View.VISIBLE);
 parallaxContainer.setupChildren(getLayoutInflater(),
  R.layout.view_intro_1, R.layout.view_intro_2,
  R.layout.view_intro_3, R.layout.view_intro_4,
  R.layout.view_intro_5, R.layout.view_intro_6 ,R.layout.view_login);
 }
 }
 else{
 setContentView(R.layout.view_login);
 }
 }
}

我們看到代碼很簡單,主要是這幾句有用的代碼:

if (parallaxContainer != null) {
 parallaxContainer.setImage(iv_man);
 parallaxContainer.setLooping(false);
 iv_man.setVisibility(View.VISIBLE);
 parallaxContainer.setupChildren(getLayoutInflater(),
  R.layout.view_intro_1, R.layout.view_intro_2,
  R.layout.view_intro_3, R.layout.view_intro_4,
  R.layout.view_intro_5, R.layout.view_intro_6 ,R.layout.view_login);
}

① 將我們小人走路的那個ImageView添加到自定義控件ParallaxContainer中

② 將我們每一個的布局文件set到ParallaxContainer控件中去

這里給出R.layout.view_intro_1.xml文件代碼,其他的類似,就不給出來了(這里的x_in、x_out、y_in等屬性注意一下)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent" >
 <ImageView
 android:id="@+id/iv_0"
 android:layout_width="103dp"
 android:layout_height="19dp"
 android:layout_centerInParent="true"
 android:src="@drawable/intro1_item_0"
 app:x_in="1.2"
 app:x_out="1.2" />
 <ImageView
 android:id="@+id/iv_1"
 android:layout_width="181dp"
 android:layout_height="84dp"
 android:layout_alignParentLeft="true"
 android:layout_alignParentTop="true"
 android:layout_marginLeft="13dp"
 android:layout_marginTop="60dp"
 android:src="@drawable/intro1_item_1"
 app:x_in="0.8"
 app:x_out="0.8" />
 <ImageView
 android:id="@+id/iv_2"
 android:layout_width="143dp"
 android:layout_height="58dp"
 android:layout_alignParentRight="true"
 android:layout_alignParentTop="true"
 android:layout_marginTop="109dp"
 android:src="@drawable/intro1_item_2"
 app:x_in="1.1"
 app:x_out="1.1" />
 <ImageView
 android:id="@+id/iv_3"
 android:layout_width="48dp"
 android:layout_height="48dp"
 android:src="@drawable/intro1_item_3"
 app:x_in="0.8"
 app:x_out="0.8"
 app:a_in="0.8"
 app:a_out="0.8"
 android:layout_below="@+id/iv_0"
 android:layout_toRightOf="@+id/iv_5"
 android:layout_toEndOf="@+id/iv_5"
 android:layout_marginLeft="21dp"
 android:layout_marginStart="21dp"
 android:layout_marginTop="12dp"/>
 <ImageView
 android:id="@+id/iv_4"
 android:layout_width="fill_parent"
 android:layout_height="128dp"
 android:layout_alignParentBottom="true"
 android:layout_marginBottom="29dp"
 android:background="@drawable/intro1_item_4"
 app:a_in="0.8"
 app:a_out="0.8"
 app:x_in="0.8"
 app:x_out="0.8" />
 <ImageView
 android:id="@+id/iv_5"
 android:layout_width="260dp"
 android:layout_height="18dp"
 android:layout_alignParentBottom="true"
 android:layout_alignParentLeft="true"
 android:layout_marginBottom="16dp"
 android:layout_marginLeft="15dp"
 android:src="@drawable/intro1_item_5"
 app:a_in="0.9"
 app:a_out="0.9"
 app:x_in="0.9"
 app:x_out="0.9" />
 <ImageView
 android:id="@+id/iv_6"
 android:layout_width="24dp"
 android:layout_height="116dp"
 android:layout_alignParentBottom="true"
 android:layout_alignParentLeft="true"
 android:layout_marginBottom="35dp"
 android:layout_marginLeft="46dp"
 android:src="@drawable/intro1_item_6"
 app:x_in="0.6"
 app:x_out="0.6" />
 <ImageView
 android:id="@+id/iv_7"
 android:layout_width="45dp"
 android:layout_height="40dp"
 android:layout_alignParentBottom="true"
 android:layout_alignParentLeft="true"
 android:layout_marginBottom="23dp"
 android:layout_marginLeft="76dp"
 android:src="@drawable/intro1_item_7"
 app:a_in="0.3"
 app:a_out="0.3"
 app:x_in="0.5"
 app:x_out="0.5" />
</RelativeLayout>

第三步:好了現(xiàn)在我們一定很好奇ParallaxContainer里面的內(nèi)容,那我們從上面的方法慢慢去看,首先看一下ParallaxContainer中的setImage()方法,代碼如下:

ImageView iv;
//將小人圖片添加進來
public void setImage(ImageView iv) {
 this.iv = iv;
}

貌似沒有什么,只是將它賦值給成員變量iv,我們接著看下一個setUpChildren()方法

//添加子view
public void setupChildren(LayoutInflater inflater, int... childIds) {
 if (getChildCount() > 0) {
 throw new RuntimeException("setupChildren should only be called once when ParallaxContainer is empty");
 }
 //創(chuàng)建打氣筒
 ParallaxLayoutInflater parallaxLayoutInflater = new ParallaxLayoutInflater(
 inflater, getContext());

 //將所有的view添加到本控件上去
 for (int childId : childIds) {
 View view = parallaxLayoutInflater.inflate(childId, this);
 viewlist.add(view);
 }
 //添加視覺view
 pageCount = getChildCount();
 for (int i = 0; i < pageCount; i++) {
 View view = getChildAt(i);
 addParallaxView(view, i);
 }
 //更新ViewPagerAdapter的數(shù)量
 updateAdapterCount();
 //創(chuàng)建viewpager
 viewPager = new ViewPager(getContext());
 viewPager.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
 viewPager.setId(R.id.parallax_pager);
 //給viewpager添加滑動監(jiān)聽
 attachOnPageChangeListener();
 //設置適配器
 viewPager.setAdapter(adapter);
 //將viewpager添加到主控件中
 addView(viewPager, 0);
}

讓我們一行行代碼慢慢分析

if (getChildCount() > 0) {
 throw new RuntimeException("setupChildren should only be called once when ParallaxContainer is empty");
 }
//創(chuàng)建打氣筒
 ParallaxLayoutInflater parallaxLayoutInflater = new ParallaxLayoutInflater(
 inflater, getContext());

首先看一下這段代碼只是if判斷是否已經(jīng)調(diào)用過setUpChildren()方法,沒什么重要的,在看創(chuàng)建ParallaxLayoutInflater打氣筒對象,我們來看看ParallaxLayoutInflater的具體代碼,沒什么重要的,只是里面有一個ParallaxFactory類我們沒見過,留心一下!

package com.qianmo.xiaohongshuwelcome.parallaxpager;
import android.content.Context;
import android.view.LayoutInflater;
public class ParallaxLayoutInflater extends LayoutInflater {
 protected ParallaxLayoutInflater(LayoutInflater original, Context newContext) {
 super(original, newContext);
 setUpLayoutFactory();
 }
 private void setUpLayoutFactory() {
 if (!(getFactory() instanceof ParallaxFactory)) {
 setFactory(new ParallaxFactory(this, getFactory()));
 }
 }
 @Override
 public LayoutInflater cloneInContext(Context newContext) {
 return new ParallaxLayoutInflater(this, newContext);
 }
}

再看下面一段代碼,主要是將所有的布局文件添加到viewList集合中去,并填充到我們的布局中,我們繼續(xù)往下看

//將所有的view添加到本控件上去
 for (int childId : childIds) {
 View view = parallaxLayoutInflater.inflate(childId, this);
 viewlist.add(view);
 }

下面一段代碼主要是看拿到對應所有的子view,關(guān)鍵是我們的addParallaxView()方法,具體代碼如下:

//添加視覺view
 pageCount = getChildCount();
 for (int i = 0; i < pageCount; i++) {
 View view = getChildAt(i);
 addParallaxView(view, i);
 }
/**
 * 添加視覺view方法
 *
 * @param view
 * @param pageIndex
 */
 private void addParallaxView(View view, int pageIndex) {
 //通過遞歸方法拿到最小單元的view
 if (view instanceof ViewGroup) {
 ViewGroup viewGroup = (ViewGroup) view;
 for (int i = 0, childCount = viewGroup.getChildCount(); i < childCount; i++) {
 addParallaxView(viewGroup.getChildAt(i), pageIndex);
 }
 }
 //創(chuàng)建視覺差view綁定,并添加到集合中去
 ParallaxViewTag tag = (ParallaxViewTag) view.getTag(R.id.parallax_view_tag);
 if (tag != null) {
 tag.index = pageIndex;
 parallaxViews.add(view);
 }
 }

通過遞歸將每個布局文件中的最小單元view保存到parallaxView集合中去,但是等等,這里我們又發(fā)現(xiàn)了一個新的類ParallaxViewTag,讓我們來具體代碼

package com.qianmo.xiaohongshuwelcome.parallaxpager;
public class ParallaxViewTag {
 //綁定每一個view對應的是哪一個下標的
 protected int index;
 //x軸進入的速度
 protected float xIn;
 protected float xOut;
 protected float yIn;
 protected float yOut;
 protected float alphaIn;
 protected float alphaOut;
}

貌似很簡單,xIn、xOut貌似很熟悉和我們之前的布局文件屬性app:x_in等屬性對應了, 這樣我們就懂了,這個類是相當于一個tag類,用于記錄我們設置的特殊一些屬性,然是我們這里有一個疑問,下面這個代碼是get到tag,那我們是在哪里set里面的屬性呢?

ParallaxViewTag tag = (ParallaxViewTag) view.getTag(R.id.parallax_view_tag);

這時候我們要看看我們前面提到過的一個陌生類ParallaxFactory,看一下具體代碼

package com.qianmo.xiaohongshuwelcome.parallaxpager;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import com.qianmo.xiaohongshuwelcome.R;
public class ParallaxFactory implements LayoutInflater.Factory {
 private final LayoutInflater.Factory factory;
 private ParallaxLayoutInflater mInflater;
 private static final String[] sClassPrefixList = {
 "android.widget.",
 "android.webkit.",
 "android.view."
 };
 public ParallaxFactory(ParallaxLayoutInflater inflater, LayoutInflater.Factory factory) {
 mInflater = inflater;
 this.factory = factory;
 }
 @Override
 public View onCreateView(String name, Context context, AttributeSet attrs) {
 View view = null;
 if (context instanceof LayoutInflater.Factory) {
 view = ((LayoutInflater.Factory) context).onCreateView(name, context, attrs);
 }
 if (factory != null && view == null) {
 view = factory.onCreateView(name, context, attrs);
 }
 if (view == null) {
 view = createViewOrFailQuietly(name, context, attrs);
 }
 if (view != null) {
 onViewCreated(view, context, attrs);
 }
 return view;
 }
 protected View createViewOrFailQuietly(String name, Context context, AttributeSet attrs) {
 if (name.contains(".")) {
 return createViewOrFailQuietly(name, null, context, attrs);
 }
 for (final String prefix : sClassPrefixList) {
 final View view = createViewOrFailQuietly(name, prefix, context, attrs);

 if (view != null) {
 return view;
 }
 }
 return null;
 }
 protected View createViewOrFailQuietly(String name, String prefix, Context context,
AttributeSet attrs) {
 try {
 return mInflater.createView(name, prefix, attrs);
 } catch (Exception ignore) {
 return null;
 }
 }
 /**
 * 主要是在viewCreated的時候?qū)ag和view綁定起來
 *
 * @param view
 * @param context
 * @param attrs
 */
 protected void onViewCreated(View view, Context context, AttributeSet attrs) {
 int[] attrIds =
 {R.attr.a_in, R.attr.a_out, R.attr.x_in, R.attr.x_out, R.attr.y_in, R.attr.y_out,};
 TypedArray a = context.obtainStyledAttributes(attrs, attrIds);
 if (a != null) {
 if (a.length() > 0) {
 ParallaxViewTag tag = new ParallaxViewTag();
 tag.alphaIn = a.getFloat(0, 0f);
 tag.alphaOut = a.getFloat(1, 0f);
 tag.xIn = a.getFloat(2, 0f);
 tag.xOut = a.getFloat(3, 0f);
 tag.yIn = a.getFloat(4, 0f);
 tag.yOut = a.getFloat(5, 0f);
 view.setTag(R.id.parallax_view_tag, tag);
 }
 a.recycle();
 }
 }
}

主要看onViewCreated()方法,可以看到,這里我們將對應的每個屬性的值都set到了我們ParallaxViewTag中,我們接著看下面的代碼,調(diào)用updateAdapterCount()方法讓適配器去更新adapter的數(shù)量,這里我們可以看到適配器是繼承PagerAdapter類,用于ViewPager的適配器,這里使用LinkedList來存儲View,這個方法很好,贊一下

//更新ViewPagerAdapter的數(shù)量
 updateAdapterCount();
//具體代碼
//被調(diào)用的時候好像是0
 private void updateAdapterCount() {
 adapter.setCount(isLooping ? Integer.MAX_VALUE : pageCount);
 }
//下面是adapter的具體代碼
package com.qianmo.xiaohongshuwelcome.parallaxpager;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import java.util.LinkedList;
import static android.view.ViewGroup.LayoutParams;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
public class ParallaxPagerAdapter extends PagerAdapter {
 private int count = 0;
 private final Context context;
 private final LinkedList<View> recycleBin = new LinkedList<View>();
 public ParallaxPagerAdapter(Context context) {
 this.context = context;
 }
 public void setCount(int count) {
 this.count = count;
 }
 @Override public int getCount() {
 return count;
 }
 @Override public Object instantiateItem(ViewGroup container, int position) {
 View view;
 if (!recycleBin.isEmpty()) {
 view = recycleBin.pop();
 } else {
 view = new View(context);
 view.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
 }
 container.addView(view);
 return view;
 }
 @Override public void destroyItem(ViewGroup container, int position, Object object) {
 View view = (View) object;
 container.removeView(view);
 recycleBin.push(view);
 }
 @Override public boolean isViewFromObject(View view, Object object) {
 return view.equals(object);
 }
}

我們繼續(xù)往下看,后面的就是創(chuàng)建viewpager對象,并addview到主控件上,在attachOnPagerChangeListener()方法中添加viewpager的滑動監(jiān)聽

/創(chuàng)建viewpager
viewPager = new ViewPager(getContext());
viewPager.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
viewPager.setId(R.id.parallax_pager);
//給viewpager添加滑動監(jiān)聽
attachOnPageChangeListener();
//設置適配器
viewPager.setAdapter(adapter);
//將viewpager添加到主控件中
addView(viewPager, 0);

這里我們在onPageScrollStateChanged()方法判斷是否開啟下面小人行走的動畫,通過onPageScrolled()方法監(jiān)聽滑動的具體偏移量,通過view.setTranslationX()方法來改變對應的屬性

protected void attachOnPageChangeListener() {
 mCommonPageChangeListener = new ViewPager.OnPageChangeListener() {
 /**
 * 此方法是在狀態(tài)改變的時候調(diào)用,其中arg0這個參數(shù)
 有三種狀態(tài)(0,1,2)。arg0 ==1的時辰默示正在滑動,arg0==2的時辰默示滑動完畢了,arg0==0的時辰默示什么都沒做。
 * @param state
 */
 @Override
 public void onPageScrollStateChanged(int state) {
 Log.v(TAG, "onPageScrollStateChanged" + state);
 iv.setBackgroundResource(R.drawable.man_run);
 final AnimationDrawable animationDrawable = (AnimationDrawable) iv.getBackground();
 switch (state) {
  case 0:
  //處于展示階段
  finishAnim(animationDrawable);
  break;
  case 1:
  //正在滑動
  isEnd = false;
  animationDrawable.start();
  break;
  case 2:
  //滑動完畢
  finishAnim(animationDrawable);
  break;
 }
 }
 //判斷是否還是在左邊
 boolean isleft = false;
 /**
 * onPageScrolled(int arg0,float arg1,int arg2) ,當頁面在滑動的時候會調(diào)用此方法,在滑動被停止之前,此方法回一直得到調(diào)用。其中三個參數(shù)的含義分別為:
 * @param pageIndex 當前頁面,及你點擊滑動的頁面
 * @param offset 當前頁面偏移的百分比
 * @param offsetPixels 當前頁面偏移的像素位置
 */
 @Override
 public void onPageScrolled(int pageIndex, float offset, int offsetPixels) {
// Log.v(TAG, "onPageScrolled" + pageIndex + " offset" + offset + " offsetPixels" + offsetPixels);
 if (offsetPixels < 10) {
  isleft = false;
 }
 if (pageCount > 0) {
  pageIndex = pageIndex % pageCount;
 }
 if (pageIndex == 3) {
  if (isleft) {

  } else {
  iv.setX(iv.getLeft() - offsetPixels);
  }
 }
 ParallaxViewTag tag;
 for (View view : parallaxViews) {
  tag = (ParallaxViewTag) view.getTag(R.id.parallax_view_tag);
  if (tag == null) {
  continue;
  }
  if ((pageIndex == tag.index - 1 || (isLooping && (pageIndex == tag.index
  - 1 + pageCount)))
  && containerWidth != 0) {
  // make visible
  view.setVisibility(VISIBLE);
  // slide in from right
  view.setTranslationX((containerWidth - offsetPixels) * tag.xIn);
  // slide in from top
  view.setTranslationY(0 - (containerWidth - offsetPixels) * tag.yIn);
  // fade in
  view.setAlpha(1.0f - (containerWidth - offsetPixels) * tag.alphaIn / containerWidth);
  } else if (pageIndex == tag.index) {
  // make visible
  view.setVisibility(VISIBLE);
  // slide out to left
  view.setTranslationX(0 - offsetPixels * tag.xOut);
  // slide out to top
  view.setTranslationY(0 - offsetPixels * tag.yOut);
  // fade out
  view.setAlpha(1.0f - offsetPixels * tag.alphaOut / containerWidth);

  } else {
  view.setVisibility(GONE);
  }
 }
 }
 @Override
 public void onPageSelected(int position) {
 Log.v(TAG, "onPageSelected" + position);
 currentPosition = position;
 }
 };
 viewPager.setOnPageChangeListener(mCommonPageChangeListener);
 }

4,這里基本上就把源碼分析完了,so,既然分析完別人的源碼了下面就是結(jié)合到自己項目中去用了,當我們,想要實現(xiàn)一個翻頁從頂部斜飛入的view,那我們的布局文件代碼可以如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
android:background="@color/transparent">
 <ImageView
 android:id="@+id/iv_2"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentTop="true"
 android:layout_centerHorizontal="true"
 android:layout_marginLeft="133dp"
 android:layout_marginTop="39dp"
 android:src="@drawable/ic_launcher"
 app:x_in="1"
 app:x_out="1"
 app:y_in="0.6"
 app:y_out="0.9"/>
 <ImageView
 android:id="@+id/iv_11"
 android:layout_width="44dp"
 android:layout_height="47dp"
 android:layout_alignParentBottom="true"
 android:layout_centerHorizontal="true"
 android:layout_marginBottom="66dp"
 android:layout_marginLeft="140dp"
 android:src="@drawable/ic_launcher"
 app:x_in="1"
 app:x_out="1"
 app:y_in="-1.3"
 app:y_out="-1.3"/>
</RelativeLayout>

關(guān)于怎么在Android應用中添加一個歡迎界面就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI