【边做项目边学Android】手机安全卫士05_1:程序主界面

主界面布局(知识点:GridView)


mainscreen.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:background="@color/background"
    android:orientation="vertical" >

    <GridView
     android:id="@+id/gv_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:horizontalSpacing="10dip"
        android:verticalSpacing="20dip"
        android:numColumns="3"
        >

    </GridView>

</LinearLayout>

android:background="@color/background"--设置背景颜色,此处采用颜色资源文件(/mobilesafe/res/values/color.xml)

color.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="background">#ff404040</color>
    <color name="textcolor">#ffd0d0d0</color>

</resources> 

GridView :

android:numColumns="3"-----列数设置为3列

android:horizontalSpacing="10dip"-----两列之间的边距

android:verticalSpacing="20dip"-----两行之间的边距


数据适配MainUIAdapter(知识点:LayoutInflater,BaseAdapter )

MainUIAdapter :

package com.liuhao.mobilesafe.adapter;

import com.liuhao.mobilesafe.R;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MainUIAdapter extends BaseAdapter {

	private static final String TAG = "MainUIAdapter";
	private Context context;//用于接收传递过来的Context对象
	private LayoutInflater inflater;
	private static ImageView iv_icon;
	private static TextView tv_name;
	private SharedPreferences sp;

	public MainUIAdapter(Context context) {
		this.context = context;
		inflater = LayoutInflater.from(context);
		sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
	}

	// 数据源,子条目的文本内容
	private static String[] names = { "手机防盗", "通讯卫士", "软件管理", "任务管理", "上网管理",
			"手机杀毒", "系统优化", "高级工具", "设置中心" };

	// 数据源,子条目的对应图片
	private static int[] icons = { R.drawable.widget05, R.drawable.widget02,
			R.drawable.widget01, R.drawable.widget07, R.drawable.widget05,
			R.drawable.widget04, R.drawable.widget06, R.drawable.widget03,
			R.drawable.widget08 };

	/**
	 * How many items are in the data set represented by this Adapter.
	 * 在此适配器中所代表的数据集中的条目数
	 */
	@Override
	public int getCount() {
		return names.length;
	}

	/**
	 * Get the data item associated with the specified position in the data set.
	 * 获取数据集中与指定索引对应的数据项
	 */
	@Override
	public Object getItem(int position) {
		return position;
	}

	/**
	 * Get the row id associated with the specified position in the list.
	 * 取在列表中与指定索引对应的行id
	 */
	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		//getView()方法被调用了多少次?
		//9次?
		//GridView 控件bug
		// 使用静态变量引用来减少内存中申请的引用的个数
		Log.i(TAG, "getView" + position);

		// 得到布局文件对应的View对象
		// inflate()方法一般接收两个参数,第一个参数就是要加载的布局id,
		// 第二个参数是指给该布局的外部再嵌套一层父布局,如果不需要就直接传null。
		View view = inflater.inflate(R.layout.mainscreen_item, null);
		iv_icon = (ImageView) view.findViewById(R.id.iv_main_icon);
		tv_name = (TextView) view.findViewById(R.id.tv_main_name);

		iv_icon.setImageResource(icons[position]);
		tv_name.setText(names[position]);
		if(position == 0){
			// 从SharedPreferences获取条目的文本内容
			String name = sp.getString("lost_name", null);
			if(!"".equals(name) && null != name){
				tv_name.setText(name);
			}
		}

		return view;
	}

}

子条目的布局:

mainscreen_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="100dip"
    android:layout_height="100dip"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:background="@drawable/item_background"
    >

    <ImageView
        android:id="@+id/iv_main_icon"
        android:layout_width="60dip"
        android:layout_height="60dip"
        android:src="@drawable/ic_launcher"
        android:scaleType="fitXY"
        />

    <TextView
        android:id="@+id/tv_main_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textColor="@color/textcolor"
        android:text="程序功能"
        />
</LinearLayout> 

为每个条目添加背景图(知识点:android:shape)

item_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <!-- 边框 -->
    <stroke
        android:width="1dip"
        android:color="#ff202020"
        />

    <!-- 指定边角 -->
    <corners
        android:radius="2dip"
        />

    <!-- 指定固定颜色 -->
    <solid
        android:color="@color/background"
        />

    <!-- 渐变色 -->
    <gradient />

</shape> 

MainActivity中使用

gv_main = (GridView) this.findViewById(R.id.gv_main);
adapter = new MainUIAdapter(this);
gv_main.setAdapter(adapter);

效果:


GridView中的getView()方法被调用了多少次?9次(9个条目)?

每个条目会多次调用getView()方法;

原因:

GridView的item的layout中android:layout_height定义为wrap_content , 绘制item高度时系统并不知道item应该绘制多高,它会先取一条来试探以确定item绘制的具体高度,这样就导致多调用了一次getView方法。在滑动、长按等GridView需要重绘的情况下,getView的调用次数可能会不止多一次。

解决方法1:

由于多次调用getView()方法,每次都会重新生成一个iv_icon ,tv_name控件对象,从而产生多个对象实例,造成空间浪费。因此,一个简单的优化方法就是,将二者设置为类静态变量:

private static ImageView iv_icon;

private static TextView tv_name;

使用静态变量引用来减少内存中申请的引用的个数,这样可以在一定程度上提高效率。

后续还会有其他优化方法。

时间: 2024-08-07 08:38:14

【边做项目边学Android】手机安全卫士05_1:程序主界面的相关文章

【边做项目边学Android】手机安全卫士03:获取更新的服务器配置,显示更新对话框

配置应用程序在手机桌面显示的名称和图标-AndroidManifest.xml: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.liuhao.mobilesafe" android:versionCode="

【边做项目边学Android】手机安全卫士04_01:界面(Activity)之间的切换,Activity和任务栈

上一回说到,用户选择是否升级,若用户选择不升级,那么就要进入程序的主界面.下面要做的是从splash界面跳转到main界面. MainActivity创建 1.首先新建MainActivity: package com.liuhao.mobilesafe.ui; import com.liuhao.mobilesafe.R; import android.app.Activity; import android.os.Bundle; public class MainActivity exten

【边做项目边学Android】手机安全卫士01:splash界面ui

手机安全卫士项目是跟着黑马的视频做的. splash是飞洒.飞溅的意思,主要是用于完成一个产品logo显示,期间可以: 后台完成数据库初始化的操作 联网访问服务器,获取服务器最新信息(升级提示) 不同的日期显示出来不同logo,判断当前系统时间,素材一般从服务器上下载下来. 判断时间,根据不同时间显示不同的加载页面 布局文件:splash.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayou

【边做项目边学Android】手机安全卫士09-手机防盗界面设置向导1

本次主要做手机防盗界面的设置向导功能界面的设计. 需求: 当用户进入手机防盗界面时,判断用户是否已经进行过设置向导: 如果用户已经设置过手机防盗,则不再提示用户进入手机向导 若还没有设置,则提示用户进入设置向导界面. 具体实现: 1.当用户输入"手机防盗"密码正确时,进行判断用户是否进行过设置向导 /** * 判断用户是否进行过设置向导 * @return */ private boolean isSetup(){ return sp.getBoolean("isAlread

【边做项目边学Android】手机安全卫士07-手机防盗之进入限制

上次写到在进入手机但·防盗界面时需要有密码限制,首先第一次进入时会弹出对话框提示用户设置密码:再次进入时会要求用户输入密码:这次来具体实现上述功能. 首次登录,设置密码 首先,我们的密码是保存在SharePreference中的"password"字段里的,在登录时后台需要校验该字段是否已经设置了密码,若未设置则弹出对话框让用户设置,否则要用户输入密码进入手机防盗界面: 校验是否设置了密码 @Override protected void onCreate(Bundle savedIn

【边做项目边学Android】知识点:Intent

一. Intent的介绍 Android中提供了Intent机制来协助应用间的交互与通讯,或者采用更准确的说法是,Intent不仅可用于应用程序之间,也可用于应用程序内部的activity, service和broadcast receiver之间的交互. Intent是一种运行时绑定(runtime binding)机制,它能在程序运行的过程中连接两个不同的组件.通过Intent,你的程序可以向Android表达某种请求或者意愿,Android会根据意愿的内容选择适当的组件来响应. Inten

【边做项目边学Android】手机安全卫士10-设置向导之绑定SIM卡

上回主要做了设置向导界面的界面设计,主要涉及到界面的布局和一些控件的使用.这次要做设置向导界面的功能具体实现. 首先,4个界面分别是(重复度很大,这里就不再贴到正文中了) /mobilesafe/res/layout/setup_wizard1.xml /mobilesafe/res/layout/setup_wizard2.xml /mobilesafe/res/layout/setup_wizard3.xml /mobilesafe/res/layout/setup_wizard4.xml

【边做项目边学Android】手机安全卫士08-一些布局和显示的细节:State List

我们注意到有些应用里的按钮在点击时的显示状态和普通状态是不一样的,比如: 普通状态下: 选中状态下: 那这种效果是如何实现的呢?在Android系统中提供给我们一种方便与实现这种功能的方法即:state list drawable. StateListDrawable是在XML中定义的drawable对象,我们可以通过设置不同item下的图片来显示不同状态,这取决于 drawable对象的状态.例如,一个Button控件可以有不同的状态(点击.聚焦等),通过一系列的drawable对象,可以为每

【边做项目边学Android】手机安全卫士11-设置向导之设置安全号码

这次主要实现设置安全号码的功能,即当发现手机SIM卡信息发生改变时,会自动给安全号码发送一条报警短信.主要包括选择联系人功能.涉及到的知识点包括:带返回值的Intent,ListView数据适配器. 选择联系人功能 界面 用ListView来对读取的联系人进行展示 /mobilesafe/res/layout/select_contact.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayou