跳转后的homeActivity,要在背景上再显示功能图标,这又是一个view,而这个需要adapter去实现,详情看日志day5.15的介绍
homeactivity
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="60dp"
android:text="功能列表"
android:background="#00FF00"
android:gravity="center"
android:textSize="25sp"/>
<GridView
android:id="@+id/gv_home_nine"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:numColumns="3"/>
</LinearLayout>
item_home
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/iv_home_pic"
android:src="@drawable/ic_launcher"
android:layout_gravity="center"
android:layout_margin="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tv_home_name"
android:layout_gravity="center_horizontal"
android:text="功能"/>
</LinearLayout>
activity,注意最后一个重载方法,用来显示view的
public class HomeActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
GridView gv_home_nine = (GridView) findViewById(R.id.gv_home_nine);
gv_home_nine.setAdapter(new MyListAdapter());
}
class MyListAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return 9;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = View.inflate(HomeActivity.this, R.layout.item_home, null);
return view;
}
}
}
导入准备好的图片后,需要显示他们
希望能实现一个跑马灯效果,显示一些额外的信息,在activity_home里加上一个textView,这里用系统的控件不好实现,无法获得焦点,为了能够自动获得焦点,一进入这个activity就能显示出来,这就需要自定义控件,FocusTextView继承于textView,他要实现3个构造方法,最后重写一个方法来判断是否有焦点
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
public class FocusTextView extends TextView {
public FocusTextView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public FocusTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public FocusTextView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
//判断是否获得焦点
@Override
public boolean isFocused() {
// 返回true确保获得焦点
return true;
}
}
在layout里使用全名来调用
<com.rjl.mobilephonemanager.FocusTextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="您当前使用的是手机卫士2.0版本,当前最新版本是3.0版本,建议下载!"
android:singleLine="true"
android:textSize="14sp"
android:ellipsize="marquee"
android:focusable="true"
android:clickable="true" />
OK,现在来实现具体功能块,首先完善之前的splash的更新功能,在设置里应该有一个是否自动更新的功能,单独需要一个settingActivity,首先记得manifest里声明下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="60dp"
android:text="设置中心"
android:background="#00FF00"
android:gravity="center"
android:textSize="25sp" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_setting_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自动更新"
android:layout_margin="5dp"
android:textSize="20sp"/>
<TextView
android:id="@+id/tv_setting_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自动更新开启"
android:textSize="16sp"
android:layout_marginLeft="5dp"
android:layout_below="@+id/tv_setting_title"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
</LinearLayout>
实现点击的跳转,需要在homeactivity里实现MyOnItemClickListener
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
GridView gv_home_nine = (GridView) findViewById(R.id.gv_home_nine);
gv_home_nine.setAdapter(new MyListAdapter());
gv_home_nine.setOnItemClickListener(new MyOnItemClickListener());
}
class MyOnItemClickListener implements OnItemClickListener{
//注意position的值,在数组里是最后一个,8
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
switch (position) {
case 8:
//跳入到setting页面
Intent intent = new Intent(HomeActivity.this,SettingActivity.class);
startActivity(intent);
break;
default:
break;
}
}
}
此时再回过头想想,setting里会有多个打钩确认,如果都是这么写就繁琐了,所以可以抽出来,通过自定义组合控件来实现,settingItem,继承于relativeLayout,同样有3个构造方法
前面有一个自定义控件了,应该建一个专用的包存这一类控件
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
public class SettingItem extends RelativeLayout {
public SettingItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public SettingItem(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public SettingItem(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
}
在这三个方法里都应该初始化,需要一个方法init()
public class SettingItem extends RelativeLayout {
public SettingItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
public SettingItem(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
public SettingItem(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
//初始化,三个构造函数都需要调用它
//通过这个初始化,通过填充器将三个控件填充到这个view,再将view加入到组合控件里
//在activity_setting里组合,另需一个setting_item来实现原来的三个控件
private void init() {
// TODO Auto-generated method stub
View view= View.inflate(getContext(), R.layout.setting_item, null);
//将控件的view加载到这个view上
this.addView(view);
}
}
原来的layout里就只需要一个组合控件,但是还是要一个layout去实现组合控件里的三个控件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="60dp"
android:text="设置中心"
android:background="#00FF00"
android:gravity="center"
android:textSize="25sp" />
<com.rjl.mobilephonemanager.ui.SettingItem
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
新建一个layout setting_item,原有的三个控件弄进来
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/tv_setting_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自动更新"
android:layout_margin="5dp"
android:textSize="20sp"/>
<TextView
android:id="@+id/tv_setting_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="自动更新开启"
android:textSize="16sp"
android:layout_marginLeft="5dp"
android:layout_below="@id/tv_setting_title"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
这中间有一个问题困扰了好久,UNbound prefix,老师在的完整代码里有一个额外的前缀,后续要用到,但是目前没有,我一股脑复制进来,导致XML解析错误,更进步导致无法通过R.layout找到view,去掉那一段就好了
组合控件还有另一个实现方式,注意init(0的第三个参数,ViewGroup型的root或者是parent,因为这个组合控件的view实际上是挂在RelativeLayout上,所以第三个参数传递一个this指向他,就相当于第一种方式的addView了
至此自定义组合控件解决了,接下来实现功能,勾选上就能自动更新
点击事件,给activity_setting里的组合控件加一个ID,oncreate里调用,他是一个自定义的settingItem类
点击需要listener
settingItem = (SettingItem) findViewById(R.id.settingitem_autoupdate);
settingItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
在onclick这个callback里需要实现在整个checkbox点击都有效果,要ID
点击后面的小框框没有作用,除了框框意外的地方点击后能实现开启、关闭的字样切换
@Override
public void onClick(View v) {
// 注意通过view v来找到ID
CheckBox cb = (CheckBox) v.findViewById(R.id.cb_settingitem);
TextView tv_setting_description = (TextView) v.findViewById(R.id.tv_setting_description);
if(cb.isChecked()){
//勾上点击后要置成false
cb.setChecked(false);
tv_setting_description.setText("自动更新关闭");
}else{
cb.setChecked(true);
tv_setting_description.setText("自动更新开启");
}
}
});
现在要保存用户对此项的设置,SharedPreferences,另外,由于之前一进去就是写死的显示是开启,我们应该根据保存状态来显示是开启还是关闭,所以这个通过ID来获取view应该拉出来通过settingitem获取,而不是在onclick里用v来获取控件在layout里写入的。这一部分的逻辑有点乱
public class SettingActivity extends Activity {
private CheckBox cb;
private TextView tv_setting_description;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
final SharedPreferences sp = getSharedPreferences("config", MODE_PRIVATE);
SettingItem settingItem = (SettingItem) findViewById(R.id.settingitem_autoupdate);
cb = (CheckBox) settingItem.findViewById(R.id.cb_settingitem);
tv_setting_description = (TextView) settingItem.findViewById(R.id.tv_setting_description);
//默认是true
boolean ischeck= sp.getBoolean("autoupdate", true);
cb.setChecked(ischeck);
if (ischeck) {
tv_setting_description.setText("自定更新开启");
}
else {
tv_setting_description.setText("自定更新关闭");
}
settingItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Editor editor = sp.edit();
if(cb.isChecked()){
//勾上点击后要置成false
cb.setChecked(false);
tv_setting_description.setText("自动更新关闭");
editor.putBoolean("autoupdate", false);
}else{
cb.setChecked(true);
tv_setting_description.setText("自动更新开启");
editor.putBoolean("autoupdate", true);
}
editor.commit();
}
});
}
}
OK,现在要判断用户是否设置了自动更新再决定是否下载,回到splashActivity调用SharedPreferences
能这样直接调用enterHome()吗?如果用户没有设置自动更新,这样不就永远不会更新了?
如果用户没有设置自动更新,则应该是提示用户是否更新,需要给一个超时时间,而不是直接enterHome(),不能直接在主线程中等待,而是需要子线程,主线程只是刷UI滴哟
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
TextView tv_splash_version = (TextView) findViewById(R.id.tv_splash_version);
//上面的声明要注意是空字符串,而不是null
tv_splash_version.setText("版本: "+getVersion());
//解析下载进度
tv_splash_downloadprogress = (TextView) findViewById(R.id.tv_splash_downloadprogress);
//需要判断用户的设置,如果用户设置了自动更新,则就打开,else 直接进入主界面
SharedPreferences sp =getSharedPreferences("config", MODE_PRIVATE);
if(sp.getBoolean("autoupdate", true)){
Update();
}else{
//如果用户没有设置自动更新,则应该是提示用户是否更新,需要给一个超时时间,而不是直接enterHome()
//不能直接在主线程中等待,而是需要子线程
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//主线程睡后,由这个将enterHome交给主线程,相当于给主线程发了消息
runOnUiThread(new Runnable() {
public void run() {
enterHome();
}
});
}
}).start();
}
}