热门手机应用界面分析--微信欢迎页面

我们知道,微信等手机应用在第一次启动时有欢迎界面,用于介绍程序的特性及使用方式:



那么我们可以针对这个界面分析:

我们启动monitor.bat,我们观察页面布局:

在TreeView窗口中我们看到有好几个Layout布局嵌套,直到我们看到一个Gallery,OK,我们大致知道了实现思路。

下面我们针对上面的一个页面进行分析。

我们看到页面上的内容是分成共几块个区域:

  • 一个RelativeLayout负责显示当前区域;另一个RelativeLayout负责显示移入效果;
  • 一个ImageView负责显示那几个小人;
  • 一个TextView负责显示那段文字;
  • 使用3个ImageView来负责显示当前处于哪个页面;


下面我们需要去找对应的Layout:

我们解压缩安装包,基本可以肯定布局文件应该是whats_news.xml,可惜混淆掉了~~~,没关系,我们可以Do It Youself, Let's go!



核心代码:

应用首次启动的判断(在主窗口中):

        boolean firstLogin = PreferenceManager.getDefaultSharedPreferences(this).getBoolean(FLAG_FIRST_LOGIN, true);
        if (firstLogin) {
            startActivity(new Intent("com.freesoft.whatsnew.activity.WelcomeActivity"));
        }

在应用程序中配置这个welcome activity的过滤器:

        <activity
            android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
            android:name="com.freesoft.whatsnew.activity.WelcomeActivity"
            android:label="guider" >
            <intent-filter>
                <action android:name="com.freesoft.whatsnew.activity.WelcomeActivity" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

这个WelcomeActivity的代码:

布局文件:

<?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.freesoft.whatsnew.component.WelcomeGallery
        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.freesoft.whatsnew.component.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>

Java代码:

package com.freesoft.whatsnew.activity;


import com.freesoft.whatsnew.R;
import com.freesoft.whatsnew.component.GalleryAdapter;
import com.freesoft.whatsnew.component.PageControlView;
import com.freesoft.whatsnew.component.WelcomeGallery;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ImageView;

public class WelcomeActivity extends Activity implements OnItemSelectedListener {

    private View viewDoor = null;
    public ImageView imageLeft = null;
    public ImageView imageRight = null;
    private WelcomeGallery gallery = null;
    private GalleryAdapter adapter = null;
    private PageControlView indicateView = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.whats_news);

        initCompnents();
    }


	private void initCompnents() {
		gallery = (WelcomeGallery) findViewById(R.id.what_news_gallery);
        adapter = new GalleryAdapter(this);
        gallery.setFadingEdgeLength(0);
        gallery.setSpacing(-1);
        gallery.setAdapter(adapter);
        gallery.setOnItemSelectedListener(this);

        indicateView = (PageControlView) findViewById(R.id.what_news_page_control);
        indicateView.setIndication(gallery.getCount(), 0);
        viewDoor = findViewById(R.id.mm_door);
        imageLeft = (ImageView) findViewById(R.id.mm_left);
        imageRight = (ImageView) findViewById(R.id.mm_right);
	}


	public void openDoor() {
		viewDoor.setVisibility(View.VISIBLE);
        imageLeft.startAnimation(adapter.setAnimation(R.anim.slide_left));
        imageRight.startAnimation(adapter.setAnimation(R.anim.slide_right));
	}


	public void gotoHome() {
    	imageLeft.setVisibility(View.GONE);
    	imageRight.setVisibility(View.GONE);
        finish();
	}

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position,
            long id) {
        if (indicateView != null) {
            indicateView.setIndication(parent.getCount(), position);
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }

}

Gallery代码:

package com.freesoft.whatsnew.component;

import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.widget.Gallery;

public class WelcomeGallery extends Gallery {

    public WelcomeGallery(Context context) {
        super(context);
        setStaticTransformationsEnabled(true);
    }

    public WelcomeGallery(Context context, AttributeSet attrs) {
        super(context, attrs);
        setStaticTransformationsEnabled(true);
    }

    public WelcomeGallery(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setStaticTransformationsEnabled(true);
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        if (velocityX > 0) {
            onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, null);
        } else {
            onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
        }
        return true;
    }
}



Adapter:

package com.freesoft.whatsnew.component;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.BaseAdapter;
import android.widget.Button;

import com.freesoft.whatsnew.R;
import com.freesoft.whatsnew.activity.WelcomeActivity;

public class GalleryAdapter extends BaseAdapter implements OnClickListener, AnimationListener{

	private Context context;
    private LayoutInflater inflater = null;

    // Layout of the Gallery
    private int[] layouts = 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) {
        context = ctx;
        inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        return layouts.length;
    }

    @Override
    public Object getItem(int position) {
        return Integer.valueOf(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
        	// dynamic loading
            convertView = inflater.inflate(layouts[position], null);
            if (position == (layouts.length - 1)) {
            	// if the last page, find the button & set button on click
                Button btn = (Button) convertView
                        .findViewById(R.id.whats_new_start_btn);
                btn.setOnClickListener(this);
            }
        }
        return convertView;
    }

    @Override
    public void onClick(View v) {
    	// 最后一个页面,button开始动画
    	((WelcomeActivity)context).openDoor();
    }

	public Animation setAnimation(int resId) {
        Animation anim = AnimationUtils.loadAnimation(context, resId);
        anim.setAnimationListener(this);
        return anim;
    }

    @Override
    public void onAnimationStart(Animation animation) {
    }

    @Override
    public void onAnimationEnd(Animation animation) {
        SharedPreferences sp = PreferenceManager
                .getDefaultSharedPreferences(context);
        Editor edit = sp.edit();
        String str = context.getString(R.string.FLAG_FIRST_LOGIN);
        edit.putBoolean(str, false);
        edit.commit();
        
        ((WelcomeActivity)context).gotoHome();
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
    }

}


PageControl代码:

package com.freesoft.whatsnew.component;

import com.freesoft.whatsnew.R;

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);
		mContext = ctx;
	}

	public PageControlView(Context ctx, AttributeSet attrs) {
		super(ctx, attrs);
		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(8, 0, 8, 0);
			}
			addView(iv);
		}
	}
}


本文参考了Android给自己的app编写用户指南这篇文章,仅仅加上了自己的一些理解和经验,也感谢原作者。


另外我简化了一下原作者的代码,省略了一些动画等锦上添花的东西,比较原始的演示了一下如何实现使用向导,下载地址:实现Splash的简化版本

UniApp 是一个基于 Vue.js 的跨平台应用开发框架,它可以构建一次,运行在多个平台上,包括微信小程序、H5、iOS、Android 等。如果你想在 UniApp 中仿照微信的“发现”页面,这是一个典型的导航和内容展示界面,你可以按照以下步骤进行: 1. **设置基础结构**: - 创建一个新的 UniApp 项目:`uni create my-project` - 在 `pages` 文件夹下创建一个名为 `discovery.vue` 或者自定义名称的文件,这是你的发现组件。 ```html <template> <view class="discovery-page"> <!-- 标题栏 --> <uni-header fixed> <uni-navbar title="发现" /> </uni-header> <!-- 内容区域 --> <uni-scroll-view class="content-scroll" scroll-y> <view v-for="(item, index) in categories" :key="index" class="category-item"> <text>{{ item.title }}</text> <!-- 可能还包括图片、描述等更多元素 --> </view> </uni-scroll-view> </view> </template> <script setup> import { ref } from 'vue'; const categories = ref([ // 根据需求填充类别数据,如微信小程序的音乐、视频、小程序等分类 ]); </script> <style scoped> .discovery-page { /* 样式定制 */ } .content-scroll { height: 100%; overflow-y: auto; } .category-item { /* 单元格样式 */ } </style> ``` 2. **数据管理**: - 需要一个数组来存储“发现”页面的各个分类及其内容。可以是静态数据,也可以从API获取。 3. **动态加载和切换**: - 如果需要用户可以滚动浏览或点击切换,可以在 JavaScript 中添加事件监听和数据更新。 4. **完善交互**: - 可以根据需要添加搜索框、分享功能、顶部广告等交互元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值