android 给自己的app编写 用户引导(UserGuider)
16lz
2021-01-25
有些第三方应用(如QQ,微信等),安装后第一次使用都有个用户引导,提示用户怎么用及版本升级后新功能介绍。用 Hierarchy Viewer 工具看用户引导 是用哪些layout组成的。常见的QQ,微信 用的 Gallery,百度输入法用的是 FrameLayout。
下面就以 Gallery 实现用户引导为例。
先来图吧,有图有真相!
这个熟悉吧,仿微信当前最新版的欢迎页。安装后第一次启动这个用户引导,本例用读写SharedPrefences判断是否第一次进(代码片段):
boolean firstLogin = PreferenceManager.getDefaultSharedPreferences(this).getBoolean(FLAG_FIRST_LOGIN, true); if (firstLogin) { startActivity(new Intent("com.xyz.guider.GuiderActivity")); }
完成用户引导后把键值 first 写 false:
SharedPreferences sp = PreferenceManager .getDefaultSharedPreferences(mContext); Editor edit = sp.edit(); edit.putBoolean(FLAG_FIRST_LOGIN, false); edit.commit();
下面来贴关键代码。
用户引导布局:
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_layout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/background_holo_dark" > <com.xyz.guider.XyzGallery android:id="@+id/what_news_gallery" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:focusable="true" android:spacing="0.0dip" android:unselectedAlpha="1.2" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:background="@null" > <com.xyz.guider.PageControlView android:id="@+id/what_news_page_control" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_marginBottom="17.5dip" android:background="@null" android:gravity="bottom|center" /> </LinearLayout> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mm_door" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/background_holo_dark" android:orientation="horizontal" android:visibility="gone" > <ImageView android:id="@+id/mm_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:adjustViewBounds="true" android:scaleType="fitEnd" android:src="@drawable/whatsnew_08_01" /> <ImageView android:id="@+id/mm_right" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:adjustViewBounds="true" android:scaleType="fitEnd" android:src="@drawable/whatsnew_08_02" /> </RelativeLayout></FrameLayout>
首先继承个Gallery的类如XyzGallery:
package com.xyz.guider;import android.content.Context;import android.util.AttributeSet;import android.view.KeyEvent;import android.view.MotionEvent;import android.widget.Gallery;public class XyzGallery extends Gallery { public XyzGallery(Context context) { super(context); // TODO Auto-generated constructor stub setStaticTransformationsEnabled(true); } public XyzGallery(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub setStaticTransformationsEnabled(true); } public XyzGallery(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub setStaticTransformationsEnabled(true); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub if (velocityX > 0) { onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, null); } else { onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null); } return true; }}
有了Gallery,还要个Gallery的适配器,作为GuiderActivity的内部类,GuiderActivity主要作用是呈现并控制 用户引导 界面:
package com.xyz.guider;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.content.SharedPreferences.Editor;import android.os.Bundle;import android.preference.PreferenceManager;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.View.OnClickListener;import android.view.WindowManager;import android.view.animation.Animation;import android.view.animation.Animation.AnimationListener;import android.view.animation.AnimationUtils;import android.widget.AdapterView;import android.widget.AdapterView.OnItemSelectedListener;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.ImageView;public class GuiderActivity extends Activity implements OnItemSelectedListener { private View mViewDoor = null; private ImageView mImageLeft = null; private ImageView mImageRight = null; private XyzGallery mGallery = null; private GalleryAdapter mAdapter = null; private PageControlView mIndicateView = null; private static final String FLAG_FIRST_LOGIN = "first"; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.whats_news); mGallery = (XyzGallery) findViewById(R.id.what_news_gallery); mAdapter = new GalleryAdapter(this); mGallery.setFadingEdgeLength(0); mGallery.setSpacing(-1); mGallery.setAdapter(mAdapter); mGallery.setOnItemSelectedListener(this); mIndicateView = (PageControlView) findViewById(R.id.what_news_page_control); mIndicateView.setIndication(mGallery.getCount(), 0); mViewDoor = findViewById(R.id.mm_door); mImageLeft = (ImageView) findViewById(R.id.mm_left); mImageRight = (ImageView) findViewById(R.id.mm_right); } private class GalleryAdapter extends BaseAdapter implements OnClickListener, AnimationListener { private Context mContext; private LayoutInflater mInfater = null; private int[] mLayouts = new int[] { R.layout.whats_news_gallery_fornew_one, R.layout.whats_news_gallery_fornew_two, R.layout.whats_news_gallery_fornew_three, R.layout.whats_news_gallery_fornew_four }; public GalleryAdapter(Context ctx) { mContext = ctx; mInfater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { // TODO Auto-generated method stub return mLayouts.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return Integer.valueOf(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub if (convertView == null) { convertView = mInfater.inflate(mLayouts[position], null); if (position == 3) { Button btn = (Button) convertView .findViewById(R.id.whats_new_start_btn); btn.setOnClickListener(this); } } return convertView; } @Override public void onClick(View v) { // TODO Auto-generated method stub mViewDoor.setVisibility(View.VISIBLE); mImageLeft.startAnimation(setAnimation(R.anim.slide_left)); mImageRight.startAnimation(setAnimation(R.anim.slide_right)); } private Animation setAnimation(int resId) { Animation anim = AnimationUtils.loadAnimation(mContext, resId); anim.setAnimationListener(this); return anim; } @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub mImageLeft.setVisibility(View.GONE); mImageRight.setVisibility(View.GONE); SharedPreferences sp = PreferenceManager .getDefaultSharedPreferences(mContext); Editor edit = sp.edit(); edit.putBoolean(FLAG_FIRST_LOGIN, false); edit.commit(); GuiderActivity.this.finish(); } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub if (mIndicateView != null) { mIndicateView.setIndication(parent.getCount(), position); } } @Override public void onNothingSelected(AdapterView<?> parent) { // TODO Auto-generated method stub }}
还有个就是 用户引导 的指示器,共有几页,当前是那一页,实现起来很简单:
package com.xyz.guider;import android.content.Context;import android.util.AttributeSet;import android.widget.ImageView;import android.widget.LinearLayout;public class PageControlView extends LinearLayout { private Context mContext; public PageControlView(Context ctx) { super(ctx); // TODO Auto-generated constructor stub mContext = ctx; } public PageControlView(Context ctx, AttributeSet attrs) { super(ctx, attrs); // TODO Auto-generated constructor stub mContext = ctx; } public void setIndication(int cnt, int index) { if (index < 0 || index > cnt) index = 0; removeAllViews(); for (int i = 0; i < cnt; i++) { ImageView iv = new ImageView(mContext); iv.setImageResource(index == i ? R.drawable.page_indicator_focused : R.drawable.page_indicator_unfocused); if (i != 0 || i != cnt - 1) { iv.setPadding(4, 0, 4, 0); } addView(iv); } }}
剩下的就是些xml文件,就不贴啦。
免分下载原码路径:http://download.csdn.net/detail/zhouyuanjing/4866714
~~完~~
更多相关文章
- 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
- Android(安卓)游戏开发之服务器端
- libevent 多线程IO
- 71、Android上对Cookie的读写操作
- Android流媒体开发之路三:基于NDK开发Android平台RTSP播放器
- 代码实例 -- 在程序里检查虚拟键盘状态, 并开启关闭
- 在Android(安卓)P中默认使用TLS保护用户
- “Android第一书”作者郭霖:用心做事,结果自然水到渠成
- 安卓4.1(android 4.1) 新功能分析 新特性介绍