欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现过渡动画、引导页 Android判断是否第一次启动App

程序员文章站 2022-08-03 18:19:01
目前的app在安装后,第一次打开,都会显示两秒左右的logo,然后进入引导页。如果关闭app,再重新打开,则只会显示logo,然后直接进入主页。 最近写了这个,记录一...

目前的app在安装后,第一次打开,都会显示两秒左右的logo,然后进入引导页。如果关闭app,再重新打开,则只会显示logo,然后直接进入主页。

最近写了这个,记录一下。

首先是过渡动画,因为它不论app是否第一次启动都会显示。

这里我使用了handler的postdelayed()方法。把过渡动画的activity设为默认启动的activity。在当前activity中,执行postdelayed()方法,把延时的时长设为两秒即可。

过渡页面如下:transition_view.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" 
  android:orientation="vertical" 
  android:background="#fff" 
  > 
 
  <imageview 
    android:src="@drawable/profile" 
    android:layout_margintop="80dp" 
    android:layout_gravity="center" 
    android:layout_width="100dp" 
    android:layout_height="100dp" /> 
 
</linearlayout> 

这里因为我的图片背景是白色的,就没有设置linearlayout的背景色了,如果logo的背景色不一样,则可以进行设置。也可以直接用imageview解决。

过渡activity如下:transitionactivity.java

package com.ikok.transitionandguidingpage; 
 
import android.app.activity; 
import android.content.intent; 
import android.content.sharedpreferences; 
import android.os.bundle; 
import android.os.handler; 
import android.view.window; 
 
/** 
 * created by anonymous on 2016/3/25. 
 */ 
public class transitionactivity extends activity { 
 
  boolean isfirstin = false; 
  private intent intent; 
 
  @override 
  protected void oncreate(bundle savedinstancestate) { 
    super.oncreate(savedinstancestate); 
    requestwindowfeature(window.feature_no_title); 
    setcontentview(r.layout.transition_view); 
 
    final sharedpreferences sharedpreferences = getsharedpreferences("is_first_in_data",mode_private); 
    isfirstin = sharedpreferences.getboolean("isfirstin",true); 
    new handler().postdelayed(new runnable() { 
 
      @override 
      public void run() { 
        if (isfirstin) { 
//          toast.maketext(transitionactivity.this, "first log", toast.length_short).show(); 
          intent = new intent(transitionactivity.this, guideactivity.class); 
          transitionactivity.this.startactivity(intent); 
          transitionactivity.this.finish(); 
        } else { 
          intent = new intent(transitionactivity.this, mainactivity.class); 
          transitionactivity.this.startactivity(intent); 
          transitionactivity.this.finish(); 
        } 
      } 
    }, 2000); 
 
  } 
 
} 

显示了过渡动画后,则需要判断是否是第一次启动app了。因为根据是否是第一次启动app会判断进入引导页还是主页。
因为这个判断并不是一次执行就不需再执行了,而是每次启动app的时候都需要进行判断。所以这个判断的数据需要持久化。

且为了判断的时间很短,就不需要进行访问数据库,或者网络访问等耗时操作了。直接使用 sharedpreferences  进行处理。

首先去指定 sharedpreferences  文件的名称,如果不存在则会创建一个。创建的文件存放在 /data/data/<package name>/shared_prefs/ 目录下。

第二个参数是指定对该文件的操作模式。默认是 mode_private ,和直接传入0是一样的,表示只有当前程序才能对这个文件进行读写操作。

mode_multi_process 是用于多个程序对同一个 sharedpreferences  文件进行读写操作。

创建好了文件,接下来我们读取标志,看程序是否是第一次启动app。

getboolean("isfirstin",true); 这个是用来获取标志的,它是用来取出文件中对应的键值对。第一个参数是键,第二个参数是默认值。

它会取出对应键的值,如果没有这个键,或者没有值,则直接使用默认值,即第二个参数。因为我创建sharedpreferences  文件的时候并没有创建这个键值对。

所以,它是读不出对应的键的值的,则会直接获取到 true 值。则app判断为第一次启动。接下来使用intent,根据值,则开启了引导页即 guideactivity 。

引导页 页面如下:guide_view.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"> 
 
  <android.support.v4.view.viewpager 
    android:id="@+id/viewpager" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
 
  </android.support.v4.view.viewpager> 
 
</linearlayout> 

这里是v4包下的viewpager。引导页我决定使用viewpager+fragmentpageradapter来实现。
如果我直接通过判断viewpager是否是最后一页,再左滑进入app主页,viewpager切换到主页时候会有一点问题。可能左滑了一点,但是还想看前两张引导页,再右滑,
结果是直接进入了app主页,而不是上一张。体验感很不好,所以考虑到最后一页上有一个按钮,来进行点击进入app主页。这样体验感会好一点。

引导页activity如下:guideacitivity.java

package com.ikok.transitionandguidingpage; 
 
import android.os.bundle; 
import android.support.v4.app.fragment; 
import android.support.v4.app.fragmentactivity; 
import android.support.v4.app.fragmentpageradapter; 
import android.support.v4.view.viewpager; 
import android.view.window; 
 
import java.util.arraylist; 
import java.util.list; 
 
/** 
 * created by anonymous on 2016/3/26. 
 */ 
public class guideactivity extends fragmentactivity { 
 
  private viewpager mviewpager; 
  private fragmentpageradapter madapter; 
  private list<fragment> mfragment = new arraylist<fragment>(); 
 
  @override 
  protected void oncreate(bundle savedinstancestate) { 
    super.oncreate(savedinstancestate); 
    requestwindowfeature(window.feature_no_title); 
    setcontentview(r.layout.guide_view); 
 
    mviewpager = (viewpager) findviewbyid(r.id.viewpager); 
 
    fragment guide1 = new guide1(); 
    fragment guide2 = new guide2(); 
    fragment guide3 = new guide3(); 
 
    mfragment.add(guide1); 
    mfragment.add(guide2); 
    mfragment.add(guide3); 
 
    madapter = new fragmentpageradapter(getsupportfragmentmanager()) { 
      @override 
      public fragment getitem(int position) { 
        return mfragment.get(position); 
      } 
 
      @override 
      public int getcount() { 
        return mfragment.size(); 
      } 
    }; 
 
    // 为viewpager添加动画效果,3.0以上可用 
    mviewpager.setpagetransformer(true,new depthpagetransformer()); 
//    mviewpager.setpagetransformer(true,new zoomoutpagetransformer()); 
    mviewpager.setadapter(madapter); 
 
  } 
} 

中间创建了三个fragment,去加载布局,布局就是在xml的根节点上添加了 background 属性。

这里我为viewpager的切换添加了切换动画。使用的 google 官方文档上列出的两种动画效果。

当然可以进行自定义切换动画,我本来自定义了一个切换20度角的切换动画,但觉得不是很好看就没放上来了。

切换动画,低版本不支持。又添加了 nineoldandroid ,来使动画兼容到低版本。

最后一个页面如下:guide_view3.xml

<?xml version="1.0" encoding="utf-8"?> 
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="match_parent" 
  android:background="@drawable/guide3"  
  android:layout_height="match_parent"> 
 
  <button 
    android:id="@+id/into_app_btn" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="进入app" 
    android:textcolor="#fefefe" 
    android:background="@drawable/button_shape" 
    android:layout_alignparentbottom="true" 
    android:layout_centerinparent="true" 
    android:layout_marginbottom="50dp" 
    /> 
 
</relativelayout> 

第三页的代码如下: guide3.java

package com.ikok.transitionandguidingpage; 
 
import android.content.intent; 
import android.content.sharedpreferences; 
import android.os.bundle; 
import android.support.v4.app.fragment; 
import android.view.layoutinflater; 
import android.view.view; 
import android.view.viewgroup; 
import android.widget.button; 
 
/** 
 * created by anonymous on 2016/3/27. 
 */ 
public class guide3 extends fragment { 
 
  private button mintoappbtn; 
  private view view; 
 
  @override 
  public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { 
    view = inflater.inflate(r.layout.guide_view3,container,false); 
    return view; 
  } 
 
  @override 
  public void onactivitycreated(bundle savedinstancestate) { 
    super.onactivitycreated(savedinstancestate); 
    mintoappbtn = (button) view.findviewbyid(r.id.into_app_btn); 
    mintoappbtn.setonclicklistener(new view.onclicklistener() { 
      @override 
      public void onclick(view v) { 
        intent intent = new intent(getactivity(), mainactivity.class); 
        startactivity(intent); 
 
        sharedpreferences sharedpreferences = getactivity().getsharedpreferences("is_first_in_data", 0x0000); 
        sharedpreferences.editor editor = sharedpreferences.edit(); 
        editor.putboolean("isfirstin", false); 
        editor.commit(); 
 
        getactivity().finish(); 
      } 
    }); 
  } 
} 

这里我就对页面上的button绑定了一个点击事件监听器。点击进入主页,并且修改判断是否第一次进入app的标志值。
通过 sharedpreferences.editor 对象去修改标志值。然后 commit ,没有 commit 是没有进行更新保存的。

这里getsharedpreferences() 的第二个参数,我直接使用了 0x0000,十六进制的0。

因为当时我使用 mode_private 的时候报错,然后我就通过查源码,发现 mode_private 的值就是 0x0000,所以我直接使用了这个 0x0000。

为什么报错呢?因为 mode_private 是context 里的变量,在 fragment 里无法识别。如果一定要用,则使用 context.mode_private。

为什么 activity 能用呢?因为 activity 继承了 context, 而 fragment 没有继承 context。

本来我做的是在主页的activity中去修改这个标志值。但是后面考虑到,如果不是第一次启动,每次进入到主页,都需要修改一次标志值,即使它没有变化,还是多做了很多无用功。所以在最后一页的点击事件里进行修改。标志值只需要修改一次,引导页也只出现一次,正好。

主页就是创建工程默认的主页了。

其他事项:

给button加了样式属性。
button_shape.xml

<?xml version="1.0" encoding="utf-8"?> 
<shape 
  xmlns:android="http://schemas.android.com/apk/res/android" 
  android:shape="rectangle"> 
  <!-- 填充的颜色 --> 
  <solid android:color="#00ffffff" /> 
  <stroke android:color="#fefefe" 
      android:width="1dp" 
    /> 
  <!-- 设置按钮的四个角为弧形 --> 
  <!-- android:radius 弧形的半径 --> 
  <corners android:radius="5dip" /> 
 
  <!-- padding:button里面的文字与button边界的间隔 --> 
  <padding 
    android:left="10dp" 
    android:top="10dp" 
    android:right="10dp" 
    android:bottom="10dp" 
    /> 
</shape> 

进入程序会出现一瞬间的空白,然后显示正常。这是因为apptheme。这里我新建了一个空的样式。然后让默认启动的activity去应用空的样式。
style.xml

<pre name="code" class="html"><resources> 
 
  <!-- base application theme. --> 
  <style name="apptheme" parent="theme.appcompat.light.darkactionbar"> 
    <!-- customize your theme here. --> 
    <item name="colorprimary">@color/colorprimary</item> 
    <item name="colorprimarydark">@color/colorprimarydark</item> 
    <item name="coloraccent">@color/coloraccent</item> 
  </style> 
 
  <!--空程序样式--> 
  <style name="emptytheme"> 
 
  </style> 
 
</resources> 

androidmanifest.xml

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  package="com.ikok.transitionandguidingpage"> 
 
  <application 
    android:allowbackup="true" 
    android:icon="@drawable/profile" 
    android:label="@string/app_name" 
    android:supportsrtl="true" 
    android:theme="@style/apptheme"> 
    <activity android:name=".mainactivity"> 
 
    </activity> 
    <!--应用空样式--> 
    <activity android:name=".transitionactivity" 
          android:theme="@style/emptytheme"> 
      <intent-filter> 
        <action android:name="android.intent.action.main" /> 
 
        <category android:name="android.intent.category.launcher" /> 
      </intent-filter> 
    </activity> 
    <activity android:name=".guideactivity"> 
 
    </activity> 
  </application> 
 
</manifest> 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。