您的位置:首页 > 移动开发 > Android开发

Android Launcher应用(基础版)

2011-11-23 12:46 162 查看
因为最近再弄android相关东西,就想自己弄个桌面程序。

现在只是弄了个大概,以后会完善起来。

功能:展示所有应用程序,单击图标打开,长按图标震动一下,并在图标的左上方出现一个删除图标,用户再单击时就会提示卸载应用程序(没有实现卸载)。

首先我们创建自己的工程Launcher。

然后我们在AndroidManifest.xml

<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
之后我们的AndroidManifest.xml就变成了:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.wch.launcher" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name="BenHome" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

</application>
<uses-permission android:name="android.permission.VIBRATE" />
</manifest>


也就是当用户按下home键的时候我们就要运行我们的桌面程序,那么就需要用户去选择是启动系统默认还是我们自己的。

接下来我们看我们的MianActivity,增加以下方法来获取当前系统的所有应用程序的信息:

private List<ResolveInfo> loadApps() {
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
return getPackageManager().queryIntentActivities(mainIntent, 0);
}


然后我们再来设置我们显示应用程序的UI,我们就采用最基本的GridView来显示。

在此之前我们先需要看下colors.xml这个很简单。

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="bg_color">#e1e7e8</color>
<color name="text_color">#000000</color>
<color name="button_selected_start_color">#0091e6</color>
<color name="button_selected_end_color">#10c0f7</color>
<color name="button_pressed_start_color">#0091e6</color>
<color name="button_pressed_end_color">#10c0f7</color>
<color name="button_defalut_start_color">#bdbebd</color>
<color name="button_defalut_end_color">#f7f3f7</color>
<color name="button_solid_color">#848284</color>
<color name="button_solid_focused_color">#e5e9ef</color>
</resources>


主要是设定了一个背景色,以及待会我们要说的gridview click时的样式。

好我们继续看layout文件:

applist.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:background="@color/bg_color"
android:layout_height="fill_parent">
<GridView android:layout_width="fill_parent"
android:listSelector="@color/bg_color"
android:id="@+id/apps_list"
android:numColumns="4"
android:layout_height="wrap_content">
</GridView>
</LinearLayout>


在此我们注意我设置了LinearLayout的background和GridView的listSelector是一样,这是保证不会再click的时候我们的item出现一个系统默认的边框。

applistitem.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:paddingBottom="4dip"
android:background="@drawable/bg_alibuymenu_states"
android:layout_width="fill_parent">
<ImageView android:layout_height="50dip"
android:id="@+id/ItemImage"
android:layout_marginTop="20dip"
android:layout_width="50dip"
android:layout_centerHorizontal="true">
</ImageView>
<TextView android:layout_width="wrap_content"
android:gravity="center"
android:textColor="@color/text_color"
android:singleLine="true"
android:textSize="16dip"
android:layout_below="@+id/ItemImage"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:id="@+id/ItemText">
</TextView>
</RelativeLayout>


这个文件大家都明白吧,就是GridView中显示的View的layout内容,采用了相对布局,并设定了background为drawable下自己设定的风格文件。

接下来我们看click的风格样式,很简单。

bg_alibuymenu_states.xml

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/bg_alibuybutton_selected" />
<item android:state_focused="true" android:drawable="@drawable/bg_alibuybutton_selected" />
</selector>


bg_alibuybutton_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="3dp" />
<stroke android:width="0.5dp" android:color="#62809a" />
<gradient android:startColor="@color/button_selected_start_color"
android:endColor="@color/button_selected_end_color" android:type="linear"
android:angle="90" android:centerX="0.5" android:centerY="0.5" />
</shape>


bg_alibuybutton_default.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="3dp" />
<stroke android:width="0.5dp" android:color="#62809a" />
<gradient android:startColor="@color/button_defalut_start_color"
android:endColor="@color/button_defalut_end_color" android:type="linear"
android:angle="90" android:centerX="0.5" android:centerY="0.5" />
</shape>


大家注意在bg_alibuymenu_states.xml文件中我们没有设定default的样式,因为我不想加任何内容,如果大家需要可以自己修改bg_alibuybutton_default.xml并自己在
bg_alibuymenu_states.xml文件中加上

<item android:drawable="@drawable/bg_alibuybutton_default" />


搞定了这些周边工作我们就来看具体代码的实现:

我做了一个适配器(AppAdapter.java)来填充gridview,

public class AppAdapter extends BaseAdapter {

final public static int OPEN = 0;
final public static int DELETE = 1;
private Map<Integer, Integer> isOpen;
public Map<Integer, Integer> getIsOpen() {
return isOpen;
}
private LayoutInflater mInflater;
private List<ResolveInfo> mApps;
private Context context;
public AppAdapter(Context context,List<ResolveInfo> mApps){

this.context = context;
this.mApps = mApps;
this.mInflater = LayoutInflater.from(this.context);
isOpen = new HashMap<Integer, Integer>();
for (int i = 0; i < this.mApps.size(); i++) {
isOpen.put(i, OPEN);
}
}

@Override
public int getCount() {
return mApps.size();
}

@Override
public Object getItem(int arg0) {
return null;
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.applistitem, null);
holder.image = (ImageView) convertView.findViewById(R.id.ItemImage);
holder.text = (TextView) convertView.findViewById(R.id.ItemText);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ResolveInfo info = this.mApps.get(position);
holder.text.setText(info.activityInfo.loadLabel(context.getPackageManager()));
holder.info = info;
holder.position = position;
holder.flag = isOpen.get(position);
if(holder.flag == OPEN){
holder.image.setImageDrawable(info.activityInfo.loadIcon(context.getPackageManager()));
}
if(holder.flag == DELETE){
BitmapDrawable bd = (BitmapDrawable)holder.info.activityInfo.loadIcon(context.getPackageManager());
try {
holder.image.setImageBitmap(drawImageAtBitmap(bd.getBitmap(),
BitmapFactory.decodeStream(context.getResources().getAssets().open("delete.png"))));
} catch (IOException e) {
Log.e("异常:", e.getMessage());
}
}

/************************************/
convertView.setOnLongClickListener(new OnLongClickListener(){

@Override
public boolean onLongClick(View view) {
ViewHolder holder = (ViewHolder)view.getTag();
if(holder.flag == OPEN){
Vibrator mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
long [] pattern = {100,400};
mVibrator.vibrate(pattern,-1);
view.startAnimation(AnimationUtils.loadAnimation(context,R.anim.anim_move));
try {
BitmapDrawable bd = (BitmapDrawable)holder.info.activityInfo.loadIcon(context.getPackageManager());
holder.image.setImageBitmap(drawImageAtBitmap(bd.getBitmap(),
BitmapFactory.decodeStream(context.getResources().getAssets().open("delete.png"))));
} catch (IOException e) {
Log.e("异常:", e.getMessage());
}
isOpen.put(holder.position, DELETE);
holder.flag = DELETE;
}else{
Toast.makeText(context, "已经处于删除状态...", Toast.LENGTH_SHORT).show();
}
return false;
}
});
convertView.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View view) {
ViewHolder vh = (ViewHolder)view.getTag();
if(vh.flag == AppAdapter.OPEN){
Toast.makeText(AppAdapter.this.context, vh.text.getText().toString(), Toast.LENGTH_SHORT).show();
String pkg = vh.info.activityInfo.packageName;
String cls = vh.info.activityInfo.name;
Intent i = new Intent();
i.setComponent(new ComponentName(pkg, cls));
AppAdapter.this.context.startActivity(i);
}
if(vh.flag == AppAdapter.DELETE){
new AlertDialog.Builder(AppAdapter.this.context)
.setTitle("提示:")
.setMessage("确定要卸载该应用程序嘛?")
.setCancelable(true)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
}).show();
}
}
});

return convertView;
}

public static Bitmap drawImageAtBitmap(Bitmap bitmap,Bitmap addBitmap){

int x = bitmap.getWidth();
int y = bitmap.getHeight();
Bitmap newbit = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newbit);
Paint paint = new Paint();
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.drawBitmap(Bitmap.createBitmap(addBitmap, 0, 0, 12, 12), 0, 0, paint);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
return newbit;
}

public final class ViewHolder {
public Integer position;
public ImageView image;
public TextView text;
public ResolveInfo info;
public int flag;
}

}


我要说明的是,ViewHolder类的flag属性是用来表示View当前的status的,也就是处于正常情况下还是删除情况下。
代码我就不详解了,看不明白的留言。
BenHome.java

public class BenHome extends Activity {

private AppAdapter mAdapter;
private GridView appList;
private List<ResolveInfo> mInfo;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.applist);
this.loadApps();
appList = (GridView)this.findViewById(R.id.apps_list);
mAdapter = new AppAdapter(this,mInfo);
appList.setAdapter(mAdapter);
}

private void loadApps() {
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mInfo = getPackageManager().queryIntentActivities(mainIntent, 0);
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
boolean isHasDelete = false;
if(mAdapter.getIsOpen().size() > 0){
for(int i : mAdapter.getIsOpen().keySet()){
if(mAdapter.getIsOpen().get(i) == AppAdapter.DELETE){
isHasDelete = true;
mAdapter.getIsOpen().put(i, AppAdapter.OPEN);
}
}
}
if(isHasDelete){
mAdapter.notifyDataSetChanged();
return true;
}else{
this.finish();
}
}
return super.onKeyDown(keyCode, event);
}
}


动画:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="-3%p" android:toXDelta="3%p" android:duration="50" android:repeatCount="10"/>
</set>



在按下返回物理键时如若有存在可删除的应用图标,就取消掉。

所需图标:




截图有瑕疵是因为图标在震动。

谁能告诉我怎么上传附件。我把源码上传上来。

源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐