阶段性总结02:
1)关于功能(代码)复用
2)popUpWindow的使用
3)对于button样式的理解
4)本地数据库查询
5)listView使用baseAdapter做适配&数据排序
6)自定义控件之圆形进度条
7)GoogleMapAPI的应用和遇到的奇特的JSON解析
8)半透明的activity效果实现
9)自定义dialog
10)动态布局切换的理解
1) 关于功能(代码)复用
其实这个问题,应该是最开始的时候,对APP功能架构了解之后的理解。
这一次,有几个地方的功能,是关联起来的,比如进度条的进度,在Home页的和子模块里面是同一个进度,虽然可能控件不太一样。那么这计算进度的部分的代码在写的时候就要考虑到复用,或者说其他地方能调用。
比如同一个功能请求,这一次,是好几个地方都提供了(调整)定位的请求,那么这个定位的模块实现,就应该在写的时候考虑到独立抽取出来。省的在后来融合的时候,需要在改动。
2) popUpWindow的使用
直接上代码
btn_menu = (ImageButton) findViewById(R.id.title_btn_setting_);
btn_menu.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (popupwindow != null && popupwindow.isShowing()) {
popupwindow.dismiss();
return;
} else {
initPopupWindowView();
popupwindow.showAsDropDown(v, 0, 5);
// popupwindow.showAtLocation(v, Gravity.CENTER, 0, 0);//居中显示popUpWindow
}
}
private void initPopupWindowView() {
// TODO Auto-generated method stub
final View menuview = LayoutInflater.from(
getApplicationContext()).inflate(R.layout.title_menu,
null);
int popwidth = dip2px(getApplicationContext(), 180);//这里需要一个dip和px的转换
int popheight = dip2px(getApplicationContext(), 210);
popupwindow = new PopupWindow(menuview, popwidth, popheight);
popupwindow.setBackgroundDrawable(getApplicationContext()
.getResources().getDrawable(R.drawable.popup_menu_bg));
popupwindow.setFocusable(true);
popupwindow.setTouchable(true);
popupwindow.setOutsideTouchable(false);
LinearLayout Item_update = (LinearLayout) menuview
.findViewById(R.id.menu_update);
LinearLayout Item_setting = (LinearLayout) menuview
.findViewById(R.id.menu_setting);
LinearLayout Item_about = (LinearLayout) menuview
.findViewById(R.id.menu_about);
LinearLayout Item_feedback = (LinearLayout) menuview
.findViewById(R.id.menu_feedback);
LinearLayout Item_share = (LinearLayout) menuview
.findViewById(R.id.menu_share);
Item_update.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "update", 1000).show();
}
});
}
});
public static int dip2px(Context c, int px) {
final float scale = c.getResources().getDisplayMetrics().density;
return (int) (px * scale + 0.5f);
}
3) 对于button样式的理解
按钮的有两个状态,一个是normal的,一个是pressed的状态的,然后就写一个selector,然后动态布局直接用这个selector吧,其实背景图片src和selector没有什么区别的,一样的用,.或者如果是写在xml里面的按钮,直接用背景图片src属性就好了。
<ImageButton
android:id="@+id/btn_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:layout_centerInParent="true"
android:layout_below="@id/img_preview"
android:src="@drawable/ac_card_download_selector"/>
4) 本地数据库查询
本地数据库,这一次是直接放在本地的assert里面的一个.db文件。
//查询数据库获取章节信息
private ArrayList<Bean_quran> getDB() {
//把本地数据库写入手机缓存
if (!new File("/data/data/" + this.getPackageName() + "/quran.sqlite")
.exists()) {
try {
FileOutputStream out = new FileOutputStream("data/data/"
+ this.getPackageName() + "/quran.sqlite");
InputStream in = getAssets().open("quran_v2_x.db");
byte[] buffer = new byte[1024];
int readBytes = 0;
while ((readBytes = in.read(buffer)) != -1)
out.write(buffer, 0, readBytes);
in.close();
out.close();
} catch (IOException e) {
}
}
//查询手机缓存里面的DB
sqliteDB_quran = SQLiteDatabase.openOrCreateDatabase(
"/data/data/" + this.getPackageName() + "/quran.sqlite", null);
System.out.println("sqliteDB");
ArrayList<Bean_quran> quran_chapters = new ArrayList<Bean_quran>();
try {
result = sqliteDB_quran
.rawQuery(
"select name_chinese, name_transliteration,sura,name_arabic,ayas_count from chapters",
null);
while (result.moveToNext()) {
chapter = new Bean_quran();
String chinese = result.getString(result
.getColumnIndex("name_chinese"))
+ "("
+ result.getString(result.getColumnIndex("ayas_count"))
+ ")";
String sura = result.getString(result.getColumnIndex("sura"));
String transliteration = result.getString(result
.getColumnIndex("name_transliteration"));
String arabic = result.getString(result
.getColumnIndex("name_arabic"));
chapter.setSura(sura);
chapter.setName_transliteration(transliteration);
chapter.setName_chinese(chinese);
chapter.setName_arabic(arabic);
quran_chapters.add(chapter);
Log.d(LOG_TAG, "--" + sura + "--" + chinese + "--"
+ transliteration + arabic);
}
result.close();
} catch (Exception e) {
e.printStackTrace();
}
return quran_chapters;
}
5) listView使用baseAdapter做适配&数据排序
其实现在发现,最复杂的的适配器,其实也是最方便的适配器,接受各种各样的item样式的定制。
首先要写一个ViewHolder类,里面的元素对应你要定制的item的样式,有图片就放img,有文字就放文字,我的布局是文字。
static class ViewHolder {
public TextView sura, name_transliteration, name_chinese, name_arabic;
}
然后就是自定义自己的adapter继承一下BaseAdapter。重写里面相应的方法。主要的是getView()
private class Myadapter extends BaseAdapter {
private LayoutInflater mInflater = null;
private Myadapter(Context context) {
this.mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return 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
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item_quran_chapter,
null);
holder.sura = (TextView) convertView
.findViewById(R.id.suraNumberTextView);
holder.name_transliteration = (TextView) convertView
.findViewById(R.id.suraNameTranslationTextView);
holder.name_chinese = (TextView) convertView
.findViewById(R.id.suraDetailTextView);
holder.name_arabic = (TextView) convertView
.findViewById(R.id.suraNameArabicTextView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.sura.setText((String) data.get(position).getSura());
holder.name_transliteration.setText((String) data.get(position)
.getName_transliteration());
holder.name_chinese.setText((String) data.get(position)
.getName_chinese());
holder.name_arabic.setText((String) data.get(position)
.getName_arabic());
return convertView;
}
}
对于查询数据库的arrayList结果需要排序处理的话。首先把list数据放到一个Comparator()方法里面。然后重写这个方法。这个方法是系统封装好了的,继承出来之后,没有实现的接口就会自己出来了。
Comparator<Bean_mosque> comparator=new comprator();
Collections.sort(mosArrayList, comparator);
//对列表数据,按照距离大小从小到大排序
public class comprator implements Comparator<Bean_mosque> {
@Override
public int compare(Bean_mosque lhs, Bean_mosque rhs) {
// TODO Auto-generated method stub
Bean_mosque aBean_mosque=(Bean_mosque)lhs;
Bean_mosque bBean_mosque=(Bean_mosque)rhs;
//这里的前后顺序改一下就是从大到小
return (aBean_mosque.getDistance()-bBean_mosque.getDistance());
}
}
6) 自定义控件之圆形进度条
之前不知道进度条怎么实现,因为他不是单纯的画扇形,后来看了gitHub上抓到的,理解了,其实是上下两个实心圆,中间一个用canvas画扇形。
7) Google返回的奇特的JSON解析
"results" : [ { "address_components" : [ { "long_name" : "安家楼村路", "short_name" : "安家楼村路", "types" : [ "route" ] }, { "long_name" : "三元桥", "short_name" : "三元桥", "types" : [ "neighborhood", "political" ] }, { "long_name" : "朝阳", "short_name" : "朝阳", "types" : [ "sublocality_level_1", "sublocality", "political" ] }, { "long_name" : "北京", "short_name" : "北京", "types" : [ "locality", "political" ] }, { "long_name" : "北京市", "short_name" : "北京市", "types" : [ "administrative_area_level_1", "political" ] }, { "long_name" : "中国", "short_name" : "CN", "types" : [ "country", "political" ] } ],上面这个奇特的JSON,是个数组一样的匿名JSONObject组,不是平常看到的有一个JSONObject,或者JSONArray,直接给我来个数组。
本来准备按照数组,写死getIndex(positon)的方式获取“北京市"这个字段的,后来发现,它是变化的,数组的长度不一样。只能作罢。
后来解决方法是,进入这个JSONArray之后,这个数组元素其实就是一个JSONObject,不过是匿名的,然后对这个匿名的JSONObject解析那个有区分的字段”types“,然后
解析这个字段,找出里面是自己要的那个type之后,提取需要的同组的字段值。
try {
JSONObject mJsonObject = new JSONObject(localString);
Log.i(TAG, "startParse");
JSONArray array = mJsonObject.getJSONArray("results");
JSONObject jo = array.getJSONObject(0);
JSONArray address = jo.getJSONArray("address_components");
for (int i = 0; i < address.length(); i++) {
JSONObject obj = address.getJSONObject(i);
JSONArray type = obj.getJSONArray("types");
for (int j = 0; j < type.length(); j++) {
String type_name = type.getString(j);
if (type_name.equals("administrative_area_level_1")) {
shortname = obj.getString("short_name");
break;
}
}
if (shortname != null)
break;
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
8) 半透明的activity效果实现
半透明效果,是点进去看大图片要的效果,能够透明看到下面的。
实现是写了一个style文件。然后在需要底子透明的activity里面加上 android:theme="@style/translucent"这个标签就好了。
---style.xml
<!-- alpha -->
<style name="translucent">
<item name="android:windowBackground">@color/alpha</item>
<item name="android:windowIsTranslucent">true</item>
</style>
--manifest
<activity
android:name="com.example.sss"
android:theme="@style/translucent" >
</activity>
9) 自定义dialog
自定义的dialog,继承了Dialog类,然后和写activity差不多,重写onCreate()方法,然后写自己的逻辑部分。
10) 动态布局切换的理解
本来觉得可能要写几套布局,然后按上不同的按钮,加载相应的布局。
呵呵哒,其实不用的,写一套,很长的那种,然后放在不同的子布局里面,不用的就invisible或者gone,需要用的时候visible就好了。