依赖关系在 build.gradle 中的 配置 (在具体的项目文件夹)
# application
程序初始化 重写 Application
在 AndroidManifest 中的 <application android:name=".your app" ... 注册
可以实现一些APP启动时候的操作
# 视图 View
view 对象就是一个透明的块,可直接用
视图常量 ViewConfiguration
当前视图常量 如滚动条的宽度,BAR的高度等 通过 ViewConfiguration.get(Context) 获得
ViewGroup 是从view继承的
ImageView 只支持 本地资源或代码资源,
ImageLoader:
网络图片资源用外部库 ImageLoader.getInstance() 或建线程加载后填充
ImageLoader 的 gradle 为 compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4'
fresco: 支持圆角 加载自定义 保存宽高比
gradle 为 compile 'com.facebook.fresco:fresco:0.6.0+'
XML 为:
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/img"
android:layout_width="100dp"
android:layout_height="wrap_content"
fresco:placeholderImage="@drawable/aa"
fresco:viewAspectRatio="2"
fresco:roundedCornerRadius="10dp"
/>
代码:
初始化: Fresco.initialize(this);
Uri uri = Uri.parse(/*http://xxxx.jpg*/);
SimpleDraweeView draweeView = (SimpleDraweeView) view.findViewById(R.id.img);
draweeView.setImageURI(uri);
glide
gradle 为
compile 'com.github.bumptech.glide:glide:3.6.1'
compile 'com.android.support:support-v4:19.1.0'
无需初始化 支持GIF 圆角通过 transform() 实现或 compile 'de.hdodenhof:circleimageview:1.3.0' 实现
ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
Picasso:
compile 'com.squareup.picasso:picasso:2.5.2'
无需初始化 圆角通过 transform() 实现或 compile 'de.hdodenhof:circleimageview:1.3.0' 实现
Picasso.with(context)
.load(R.drawable.landing_screen)
.placeholder(R.id.progressBarDetails)
.error(R.drawable.friend_request)
.into(imageView1);
Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2);
Picasso.with(context).load(new File(...)).into(imageView3);
//自定义下载
Picasso picasso = new Picasso.Builder(myslideAcitivty.this).downloader(
//OkHttpDownloader
//UrlConnectionDownloader
new OkHttpDownloader(new File(imageCacheDir))
).build();
ImageView 宽高比 https://github.com/hongyangAndroid/android-percent-support-extend
视图在 onCreate onStart 等方法中未渲染,高宽为0 需要高宽请重写 onWindowFocusChanged 设置
示例:
@Override //重设margin
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
AppBarLayout abl = (AppBarLayout) findViewById(R.id.app_bar_layout);
LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout);
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)ll.getLayoutParams();
layoutParams.topMargin=abl.getHeight();
ll.setLayoutParams(layoutParams);
}
设置布局:setLayoutParams 为父布局类型
LinearLayout LayoutHead = (LinearLayout)findViewById(R.id.layline);
Button DateButton = (Button)findViewById(R.id.but);
//LinearLayout.LayoutParams ly=DateButton.getLayoutParams(); //ly may be null
//ly.width=100;
//DateButton.setLayoutParams(ly);
//OR
DateButton.setLayoutParams(
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
);
layoutHead.addView(DateButton);
动态加ID:
idx.xml
<resources>
<item type="id" name="return_scan_result"/>
</resources>
代码:
TextView tt = new TextView(this);
tt.setId(R.id.return_scan_result);
窗口管理,屏幕高宽等
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
获取 基本组件可以通过 ComponentName 来获取,支持Context 中获取指定的view组件
示例
new ComponentName(context, myreceiver.class);
new ComponentName("包名","类或类名")
加载提示
final ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("加载中");
dialog.show();
用在非本身的视图 RemoteViews
new RemoteViews(context.getPackageName(), R.layout.aa);
排版页面时,样式可独立到style中,通过style来引用 (类似CSS) style 通过 parent实现继承
自定义视图,继承至view 示例
定义 view
public class MyView extends View {
private Paint mPaint;
private int textColor;
public MyView(Context context) {
super(context);
mPaint = new Paint();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
//自定义属性 参考/values/attrs.xml
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
textColor = a.getColor(R.styleable.MyView_bgcolor, 0XFFFFFFFF);
float textSize = a.getDimension(R.styleable.MyView_textSize, 36);
a.recycle();
mPaint = new Paint();
mPaint.setTextSize(textSize);
mPaint.setColor(textColor);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(new Rect(10, 10, 100, 100), mPaint);
mPaint.setColor(textColor);
}
@Override //可不重写此方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//设置自己的高宽
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//父元素推荐宽高
// int w = MeasureSpec.getSize(widthMeasureSpec);
// int h = MeasureSpec.getSize(heightMeasureSpec);
//当前元素的模式
// int wMode = MeasureSpec.getMode(widthMeasureSpec);
// int hMode = MeasureSpec.getMode(heightMeasureSpec);
//MeasureSpec.AT_MOST //元素的宽高超过此值将不可见
//MeasureSpec.EXACTLY //元素已指定宽或高
//MeasureSpec.UNSPECIFIED //其他
//告知父元素本身高宽
// setMeasuredDimension(w, h);
}
}
定义 /values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--name 为自定义视图类名-->
<declare-styleable name="MyView">
<!-- color:颜色值 -->
<attr name="bgcolor" format="color" />
<!-- reference:参考某一资源ID 多种类型用|分割 -->
<attr name="backgroupd" format="reference|color" />
<!-- fraction:表示百分比 -->
<attr name = "pivotX" format = "fraction" />
<!-- string:表示字符串 -->
<attr name = "apiKey" format = "string" />
<!-- integer:表示整形 -->
<attr name = "count" format="integer" />
<!-- float:表示浮点数 -->
<attr name = "namefloat" format = "float" />
<!-- dimension:表示尺寸 -->
<attr name = "namedimension" format = "dimension" />
<!-- dimension:表示布尔 -->
<attr name = "nameboolean" format = "boolean" />
<!-- flag TAG:表示可以进行位运算 使用 mode1|mode2 -->
<attr name="mode">
<flag name = "mode1" value = "0" />
<flag name = "mode2" value = "1" />
</attr>
<!-- enum TAG:选择其中一个 -->
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>
使用自定义view
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:custom="http://schemas.android.com/apk/res-auto"
>
<com.example.dome1.MyView
custom:bgcolor="#000000"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
自定义视图组
public class myviewgroup extends ViewGroup {
public ccimg(Context context) {
super(context);
}
public ccimg(Context context, AttributeSet attrs) {
super(context, attrs);
//设置属性
// TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);
// textColor = a.getColor(R.styleable.MyView_bgcolor, 0XFFFFFFFF);
// float textSize = a.getDimension(R.styleable.MyView_textSize, 36);
// a.recycle();
// mPaint = new Paint();
// mPaint.setTextSize(textSize);
// mPaint.setColor(textColor);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制自己的内容
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// 设置子视图
int padding=20,
wh=100;
for (int i = 0, size = getChildCount(); i < size; i++) {
View view = getChildAt(i);
// 放置子View,宽高都是100
view.layout(left, top, left + wh, top + wh);
left += wh + padding;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//设置自己的高宽
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//getMeasuredWidth() //运算得到实际内容宽度
//getMeasuredHeight() //运算得到实际内容高度
//父元素推荐宽高
// int w = MeasureSpec.getSize(widthMeasureSpec);
// int h = MeasureSpec.getSize(heightMeasureSpec);
//当前元素的模式
// int wMode = MeasureSpec.getMode(widthMeasureSpec);
// int hMode = MeasureSpec.getMode(heightMeasureSpec);
//MeasureSpec.AT_MOST //元素的宽高超过此值将不可见
//MeasureSpec.EXACTLY //元素已指定宽或高
//MeasureSpec.UNSPECIFIED //其他
//告知父元素本身高宽
// setMeasuredDimension(w, h);
}
}
弹出窗口
1. 对话框 Dialog 子类
一般对话框可以直接用 AlertDialog.Builder alert= new AlertDialog.Builder(this);
或者重写 AlertDialog 类实现一些自己的弹框提示 示例:
AlertDialog.Builder alert = new AlertDialog.Builder(TouchActivity.this);
alert.setTitle("Alert");
alert.setMessage("messgae");
alert.show();
或继承 dialog 示例:
public class MyCustomDialog extends Dialog {
public MyCustomDialog(Context context) {
super(context);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xxx);
//设置标题
setTitle("this is title");
Button clickBtn = (Button) findViewById(R.id.button);
clickBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyCustomDialog.this.dismiss();
}
});
}
}
2. 使用 Activity 加样式
样式:
<style name="MyDialogStyle">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
在 AndroidManifest.xml 注册
<activity android:name=".tabactivity" android:theme="@style/MyDialogStyle"></activity>
使用:
Intent i= new Intent(MainActivity.this,tabactivity.class);
startActivityForResult(i);
3. 使用 PopupWindow 类 示例:
//选择布局填充视图
View contentView = LayoutInflater.from(MainActivity.this).inflate(
R.layout.tab, null);
Button button = (Button) contentView.findViewById(R.id.button3);
//创建弹出窗口
final PopupWindow popupWindow = new PopupWindow(contentView,
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, true);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popupWindow.dismiss();//关闭
}
});
popupWindow.setTouchable(true);
popupWindow.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
popupWindow.setBackgroundDrawable(getDrawable(R.drawable.a));
popupWindow.showAsDropDown(contentView);
# 运行时授权
要添加在 AndroidManifest.xml 添加 uses-permission
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Build.VERSION.SDK_INT>=23) {
//单个
int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.CAMERA);
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
//false 表示授权拒绝
Log.i("xxx", "auth bad 4");
}else{
requestPermissions(new String[]{Manifest.permission.CAMERA},222);
}
}else{
Log.i("xxx", "auth ok 2");
}
//多个
final List permissionsNeeded = new ArrayList();
final List<String> permissionsList = new ArrayList<String>();
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(Manifest.permission.ACCESS_FINE_LOCATION);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
//false 表示授权拒绝
permissionsNeeded.add("need location");
}
}
if (checkSelfPermission(Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(Manifest.permission.WRITE_CONTACTS);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {
//false 表示授权拒绝
permissionsNeeded.add("need contats");
}
}
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
Log.i("xxx", "auth bad 1");
}
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), 111);
}else{
Log.i("xxx", "auth ok 3");
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 111:
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++ )
perms.put(permissions[i], grantResults[i]);
// Check for ACCESS_FINE_LOCATION
if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
Log.i("xxx","auth ok 4");
} else {
Log.i("xxx","auth bad 2");
}
break;
case 222:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("xxx","auth ok 1");
} else {
Log.i("xxx","auth bad 3");
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
# 视图坐标
获取屏幕区域的宽高等尺寸获取
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;
应用程序App区域宽高等尺寸获取
Rect rect = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
获取状态栏高度
Rect rect= new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rectangle.top;
View布局区域宽高等尺寸获取
Rect rect = new Rect();
getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);
View的静态坐标方法
getScrollY() 返回View竖向滚动距离
getScrollX() 返回View横向滚动距离
getLeft() 返回View自身左边到父布局左边的距离
getTop() 返回View自身顶边到父布局顶边的距离
getRight() 返回View自身右边到父布局左边的距离
getBottom() 返回View自身底边到父布局顶边的距离
getX() 返回值为getLeft()+getTranslationX(),当setTranslationX()时getLeft()不变,getX()变。
getY() 返回值为getTop()+getTranslationY(),当setTranslationY()时getTop()不变,getY()变。
MotionEvent坐标方法
getX() 当前触摸事件距离当前View左边的距离
getY() 当前触摸事件距离当前View顶边的距离
getRawX() 当前触摸事件距离整个屏幕左边的距离
getRawY() 当前触摸事件距离整个屏幕顶边的距离
View宽高方法
getWidth() layout后有效,返回值是mRight-mLeft,一般会参考measure的宽度(measure可能没用),但不是必须的。
getHeight() layout后有效,返回值是mBottom-mTop,一般会参考measure的高度(measure可能没用),但不是必须的。
getMeasuredWidth() 返回measure过程得到的mMeasuredWidth值,供layout参考,或许没用。
getMeasuredHeight() 返回measure过程得到的mMeasuredHeight值,供layout参考,或许没用。
View的方法
getLocalVisibleRect()
获取View自身可见的坐标区域,坐标以(0,0)开始,另一点为可见区域右下角相对自己(0,0)点的坐标
例子:(0, 0 - 410, 100)
getGlobalVisibleRect()
获取View在屏幕绝对坐标系中的可视区域,坐标以原点开始的坐标,另一点为可见区域右下角原点的坐标
例子:(30, 100) (30, 250)
getLocationOnScreen()
坐标是相对整个屏幕而言,Y坐标为View左上角到屏幕顶部的距离。
getLocationInWindow()
如果为普通Activity则Y坐标为View左上角到屏幕顶部(此时Window与屏幕一样大);如果为对话框式的Activity则Y坐标为当前Dialog模式Activity的标题栏顶部到View左上角的距离。
View的滑动方法
offsetLeftAndRight(int offset) 水平方向挪动View,offset为正则x轴正向移动,移动的是整个View,getLeft()会变的,自定义View很有用。
offsetTopAndBottom(int offset) 垂直方向挪动View,offset为正则y轴正向移动,移动的是整个View,getTop()会变的,自定义View很有用。
scrollTo(int x, int y) 将View中内容(不是整个View)滑动到相应的位置,参考坐标原点为ParentView左上角,x,y为正则向xy轴反方向移动,反之同理。
scrollBy(int x, int y) 在scrollTo()的基础上继续滑动xy。
setScrollX(int value) 实质为scrollTo(),只是只改变Y轴滑动。
setScrollY(int value) 实质为scrollTo(),只是只改变X轴滑动。
getScrollX()/getScrollY() 获取当前滑动位置偏移量。
# 组件调用 Intent
1. 隐式添加
向系统注册静态 Intent 在 AndroidManifest 加 intent-filter
<activity
android:name=".activity.MyActivity"
android:label="@string/ac_name_image_list" >
<intent-filter>
<action android:name="mxp"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
在 MyActivity 添加 public static final String MY_ACTION = "mxp";
启动: startActivity(new Intent(MyActivity.MY_ACTION));
关于 category 匹配
如下 AndroidManifest
<intent-filter>
<action android:name="action1" />
<category android:name="cate1"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
启动
Intent intent = new Intent("action1");
intent.addCategory("cate1");//有无都匹配
startActivity(intent);
关于 data 匹配
如下 AndroidManifest
<intent-filter>
<action android:name="action1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:mimeType="audio/*" />
<data android:pathPattern=".*.mp3" /><!-路径匹配->
</intent-filter>
启动
Uri uri=Uri.parse("file://aaaa.mp3");
Intent intent = new Intent("action1");
intent.setData(uri);
startActivity(intent);
2. 基本组件通过Intent来相互调用 setExtras getExtras 参数传递
3. PendingIntent
包装Intent,使Intent延时触发,有以下类型
PendingIntent.getBroadcast()
PendingIntent.getActivity() & PendingIntent.getActivities()
PendingIntent.getService()
4. 可通过 ComponentName 进行调用
Intent it=new Intent();
it.setComponent(new ComponentName(getPackageName(),MyActivity.class.getName()));
startActivity(it)
# 加载管理 Loader
CursorLoader 使用示例,一般使用在 Cursor 数据源下
public static class CursorLoaderListFragment extends ListFragment
implements LoaderManager.LoaderCallbacks<Cursor> {
SimpleCursorAdapter mAdapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_2, null,
new String[] { ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.CONTACT_STATUS },
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
setListAdapter(mAdapter);
getLoaderManager().initLoader(0, null, this);
}
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.CONTACT_STATUS,
ContactsContract.Contacts.CONTACT_PRESENCE,
ContactsContract.Contacts.PHOTO_ID,
ContactsContract.Contacts.LOOKUP_KEY,
};
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri baseUri;
baseUri = ContactsContract.Contacts.CONTENT_URI;
String select = "";
//返回游标Loader
return new CursorLoader(getActivity(), baseUri,
CONTACTS_SUMMARY_PROJECTION, select, null,
ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//加载完成回调,重设游标
mAdapter.swapCursor(data);
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
public void onLoaderReset(Loader<Cursor> loader) {
//重设
mAdapter.swapCursor(null);
}
}
AsyncTaskLoader 使用示例,一般用在数据加载,如列表等,
如 Activity 里多个 Fragment 时候 方便管理,只有简单数据加载 可直接用 封装AsyncTask
class myloader extends AsyncTaskLoader<List<String>>{
Bundle args;
public myloader(Context context, Bundle args) {
super(context);
this.args=args;
}
@Override
public List<String> loadInBackground() {
// 根据 this.args 不同进行处理
Log.i("myout","out");
List<String> my= new ArrayList<String>();
my.add("hi");
return my;
}
@Override
public void cancelLoadInBackground() {
//当发生取消时候调用.如请求服务器数据.这里进行取消操作
}
@Override
protected void onStartLoading() {
forceLoad();
}
@Override
protected void onStopLoading() {
cancelLoad();
}
@Override
protected void onReset() {
super.onReset();
onStopLoading();
}
}
使用AsyncTask
final ListView lv= (ListView)findViewById(R.id.listView);
final ArrayAdapter apt=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,android.R.id.text1);
lv.setAdapter(apt);
final LoaderManager.LoaderCallbacks loadercallback = new LoaderManager.LoaderCallbacks<List<Map<String,String>>>(){
@Override
public Loader<List<Map<String,String>>> onCreateLoader(int id, Bundle args) {
return new myloader(MainActivity.this,args);
}
@Override
public void onLoadFinished(Loader<List<Map<String,String>>> loader, List<Map<String,String>> data) {
apt.addAll(data);
//加载完成,进行其他视图更新
}
@Override
public void onLoaderReset(Loader<List<Map<String,String>>> loader) {
//当调用 getLoaderManager().destroyLoader(1);
apt.clear();
//进行视图清空处理等
}
};
//初始化加载
getLoaderManager().initLoader(1, null, loadercallback);
//重新加载数据
getLoaderManager().destroyLoader(1);
getLoaderManager().initLoader(1, null, loadercallback);
//重新启动加载器(非重新加载数据,如需要加载下一页数据)
getLoaderManager().restartLoader(1,b,loadercallback);
# 页面 Activity
R.drawable 图片资源
R.string 字符资源
R.menu 菜单 比较特殊的一个View 菜单填充用 MenuInflater
示例:
xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/share_item"
android:orderInCategory="100"
app:showAsAction="always"
android:title="分享"
/>
</menu>
添加及监听:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my,menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.share_item:
break;
}
return super.onOptionsItemSelected(item);
}
资源 assets 通过 getAssets().open() 来访问
资源 Resources 通过 get** 系列获取函数 如getDrawable(R.drawable.a1); 获得 drawable 对象
填充获取布局View (注意:获取到后未添加到显示视图中)
getLayoutInflater().inflate(R.layout.activity_touch, null);
((LayoutInflater){Context}.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.activity_touch, null);
ViewGroup 下 Layout 用来布局页面
LayoutInflater 处理layout XML 资源 返回View
R.id 在ids.xml有部分预设ID,在android.R.id 下 如content为当前视图根节点
ViewGroup rootnode = (ViewGroup)findViewById(android.R.id.content);//根节点
遍历ViewGroup的子视图
ViewGroup viewById = (ViewGroup)findViewById(android.R.id.content);
for (int i=0;i<viewById.getChildCount();i++)
viewById.getChildAt(i);
添加视图(ViteGroup对象可用)
TextView t=new TextView(this);
t.setText("fsadf");
rootnode.addView(t);
片段 Fragment 及管理 可添加,替换等 (未显示的页面) (XML不能是空的Fragment)
填充 附属至相应的Activity生效
通过getView() 处理里面的view
FragmentActivity 提供辅助 Fragment 的方法
示例代码
代码方式添加
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}
添加进显示
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
//添加但不显示
getFragmentManager().beginTransaction().add(ttt, "ttt").commit();
//获取
Fragment ttt = getFragmentManager().findFragmentByTag("ttt");
XML 方式添加 (必须要有id属性)
<fragment
android:id="@+id/id_fragment_title"
android:name="com.example.xxx.MainActivity$PlaceholderFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
通过 setContentView(R.layout.activity_main);
数据传递
设置
Intent intent = new Intent("action1");
intent.putExtra("test","xxx");
startActivity(intent);
获取 get...Extra 系列方法
getIntent().getStringExtra("test");
通过Uri 的数据
Uri uri=getIntent().getData();
跳转返回
//起始 Activity: 1->requestCode
{...
Intent intent=new Intent("action1");
startActivityForResult(intent, 1);
...}
@Override
rotected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode){
case 1:
switch(resultCode){
case 1:
//处理数据
break;
}
break;
}
}
//数据 Activity: 1->resultCode
setResult(1, intent);
finish();
于 Fragment 的数据传递
Activity 设置数据
PlaceholderFragment my = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putString("test","test");
my.setArguments(bundle);
在 PlaceholderFragment 的 onCreateView 中获取
Bundle arguments = my.getArguments();
# 数据适配器
1. 视图分配
a. 重写 Adapter 的getView
b. setViewBinder 重写 ViewBinder的setViewValue方法
2. BaseAdapter 基本适配器
完全自主 适配器基类 数据源可不定格式
3. SimpleAdapter 简单适配器 (简单键值对数据)
格式:Context context, List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to
提供数据(MAP LIST) 布局 数据格式 布局元素
根据提供的格式渲染
示例:
List<Map<String,String>> list= new ArrayList<Map<String, String>>();
Map<String,String> m1= new HashMap<String,String>();
m1.put("aa","aaa");
m1.put("bb", "bbb");
list.add(m1);
SimpleAdapter sa= new SimpleAdapter(this,list,R.layout.text,
new String[]{"aa","bb"},new int[]{R.id.aa,R.id.bb});
4. ArrayAdapter<T> 数组适配器 (类型固定,非简单键值对,如建模的对象,或String)
a. 简单String
示例:
ArrayAdapter aa=new ArrayAdapter<String>(this,R.layout.text,R.id.aa);
aa.add("sssssssssssss");
b. 指定类类型 一般需重写:视图分配
5. CursorAdapter 游标适配器
一般用于通过 Content Provider 的数据,如果联系人,本地数据库等
示例:
Cursor curContacts=getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.LOOKUP_KEY}, null, null, null);
CursorAdapter aa = new MyCursorAdapter(this,curContacts);
//重写 newView bindView 方法实现视图
class MyCursorAdapter extends CursorAdapter {
public MyCursorAdapter(Context context, Cursor c) {
super(context, c,true);
}
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater vi = null;
vi = getLayoutInflater();
View v=vi.inflate(R.layout.text, parent, false);
TextView view = (TextView)v.findViewById(R.id.aa);
return view;
}
@Override
public void bindView(View v, Context context, Cursor cursor) {
TextView nameView = (TextView)v.findViewById(R.id.aa);
nameView.setText(cursor
.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
}
}
6.? ResourceCursorAdapter & SimpleCursorAdapter 对 CursorAdapter 的再次封装
其中 SimpleCursorAdapter 实现了类似于 SimpleAdapter 的封装
示例:
Cursor curContacts=getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.LOOKUP_KEY}, null, null, null);
lv.setAdapter(new SimpleCursorAdapter(this,R.layout.text,curContacts,new String[]{
ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER
},new int[]{
R.id.aa,R.id.bb
},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER));
7. 数据修改
a. 数据源变动 适配器的数据为初始化时候的源,或通过适配器修改数据,将会自动反应到视图
2. 视图数据变动 修改视图后,调用适配器的 notifyDataSetChanged 方法,将会把视图数据反应到数据源
# 异步执行与数据交互
1. 请求线程创建
1. 手动创建线程
final Handler h = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bundle b= msg.getData();
//视图线程,处理视图
}
};
new Thread(){
@Override
public void run() {
//请求数据等...
Message msg= new Message();
Bundle b=new Bundle();
//设置数据
msg.setData(b);
h.sendMessage(msg);
super.run();
}
}.start();
2. 使用AsyncTask
//AsyncTask 类型: 根据需要传递
// 请求参数,进度参数,执行完返回结果
private class MyTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
//请求前调用,可处理UI
}
@Override
protected String doInBackground(String... params) {
//处理请求等操作,请求线程,不处理UI
//setProgress();操作进度
return null;
}
@Override
protected void onProgressUpdate(Integer... progresses) {
//进度操作,处理UI
}
@Override
protected void onPostExecute(String result) {
//执行完操作.处理UI
}
@Override
protected void onCancelled() {
//用户取消操作,处理UI
}
}
调用:
new MyTask().execute("/*request prams*/");
2. 请求方式
a. 使用OkHttpClient 库 compile 'com.squareup.okhttp:okhttp:2.4.0'
全局公用 OkHttpClient client= new OkHttpClient();
有 Request 请求对象 和 Response 返回对象
示例
OkHttpClient client= new OkHttpClient();
Request request = new Request.Builder().url("url").build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
return null;
}
if(response.isSuccessful()){
String c=response.body().toString();
return c;
}
b. 使用JAVA网络库
URL url;
StringBuffer sb=new StringBuffer();
try {
url=new URL("url");
InputStreamReader isr=new InputStreamReader(url.openStream());
BufferedReader br= new BufferedReader(isr);
String str;
while((str=br.readLine())!=null)
{
sb.append(str);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return sb.toString();
3. 数据处理
a. JSON 处理 (还有GSON等库可用)
内置JSON:
String json="{}";
JSONTokener jsontoken= new JSONTokener(json);
JSONObject jsonobject = null;
JSONArray jsonarr;
ArrayList<String>outarr;
try {
jsonobject = (JSONObject) jsontoken.nextValue();
//JSON 简单数据类型:
String strval=jsonobject.getString("strkey");
//JSON 复合数据类型:
jsonarr =jsonobject.getJSONArray("arrkey");
outarr =new ArrayList<String>();
for (int i=0;i<jsonarr.length();i++){
outarr.add(jsonarr.get(i).toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
String json="[]";
JSONTokener jsontoken= new JSONTokener(json);
try {
JSONArray jsonarr = (JSONArray) jsontoken.nextValue();
for (int i=0;i<jsonarr.length();i++){
JSONObject t=(JSONObject)jsonarr.get(i);
Log.i("xxx",t.getString("tit"));
}
} catch (JSONException e) {
e.printStackTrace();
}
GSON: 可以直接把JSON转成MODEL
JsonParser parser = new JsonParser();
String json1="{}";
JsonElement objel = parser.parse(json1);
if(!objel.isJsonObject()) return ;
//User u = gson.fromJson(objel, User.class);
JsonObject jobj = objel.getAsJsonObject();
Log.i("xxx",jobj.get("tit").getAsString());
String json1="{users:[]}";
JsonParser parser = new JsonParser();
JsonElement objel = parser.parse(json1);
if(!objel.isJsonObject()) return ;
JsonObject jobj = objel.getAsJsonObject();
Gson gson = new Gson();
List users = gson.fromJson(jobj.get("users"), new TypeToken<List>() {
}.getType());
String json="[]";
JsonParser parser = new JsonParser();
JsonElement el = parser.parse(json);
JsonArray jsonArray = null;
if(el.isJsonArray()){
jsonArray = el.getAsJsonArray();
}
Gson gson = new Gson();
Iterator it = jsonArray.iterator();
while(it.hasNext()){
JsonElement e = (JsonElement)it.next();
User u = gson.fromJson(e, User.class);
Log.i("xxx",u.getSrc());
}
b. XML 处理 (还有DOM SAX库可用)
try {
URL url;
url=new URL("http://www.urltest.tk/a.php");
InputStream is= null;
is = url.openStream();
XmlPullParser parser = Xml.newPullParser();
int eventType = 0;
parser.setInput(is, "UTF-8");
eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
//文档开始
break;
case XmlPullParser.START_TAG:
if (parser.getName().equals("book")) {
//标签开始
}
break;
case XmlPullParser.END_TAG:
//标签结束
break;
}
eventType = parser.next();
}
} catch (Exception e) {
e.printStackTrace();
return ;
}
# dataBinding 数据绑定 启用 android {... dataBinding { enabled = true }}
1. 视图绑定
XML:
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data class=".dataclassname">
<import type="com.example.dome2.User" alias="Myuser" />
<variable name="u" type="Myuser"/>
</data>
<TextView
android:text='@{u.hi}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/lastname"/>
</layout>
注释:
class 属性表示视图绑定类的名 可不填,根据文件名生成
import 引入其他类方式 alias 防止类冲突
variable 定义变量
used:
dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setU(/*xxx*/);// 根据 variable 自动生成方法
binding.lastname;//TextView 对象 根据 @+id 自动生成
变量使用:
普通对象 @{user.lastName}
Map 对象 @{user["lastName"]}
Liset 对象 @{user[0]}
静态方法 @{String.valueOf(1 + (Integer)user["age"])}
运算 @{user.displayName ?? user.lastName}
@{user.displayName != null ? user.displayName : user.lastName}
@{age < 13 ? View.GONE : View.VISIBLE} //<import type="android.view.View" />
@{@string/nameFormat(firstName)}
2. 数据模型
a. 自定义数据模型
//方式一 继承 BaseObservable
model:
public class User extends BaseObservable {
private String hi;
@Bindable //必须有注释,在BR 中生成对应KEY
public String getHi() {
return this.hi;
}
public void setHi(String hi){
this.hi=hi;
notifyPropertyChanged(BR.hi);//提醒修改
}
//定义属性的操作方式
//定义组件属性
//app:imageUrl="@{user.src}" 方式使用
@BindingAdapter({"bind:imageUrl"})
public static void loadImage(SimpleDraweeView view, String url) {
Uri uri = Uri.parse(url);
view.setImageURI(uri);
}
//使用自带属性
@BindingAdapter("android:paddingLeft")
public static void setPaddingLeft(View view, int padding) {
view.setPadding(padding,
view.getPaddingTop(),
view.getPaddingRight(),
view.getPaddingBottom());
}
}
xml:
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data class=".dataclassname">
<import type="com.example.dome2.User" alias="Myuser" />
<variable name="u" type="Myuser"/>
</data>
<TextView
android:text='@{u.hi}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/lastname"/>
<com.facebook.drawee.view.SimpleDraweeView
app:imageUrl="@{u.hi}"
android:id="@+id/img"
android:layout_width="100dp"
android:layout_height="wrap_content"
/>
</layout>
used:
dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User data=new User();//其他代码...
data.setHi('xxx');
binding.setU(data);
//方式二 属性用 Observable 系列类
model:
public class User{
public final ObservableField<String> lastName =
new ObservableField<>();
public final ObservableInt age = new ObservableInt();
}
xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data class=".dataclassname">
<import type="com.example.dome2.User" alias="Myuser" />
<variable name="userdata" type="Myuser"/>
</data>
<TextView
android:text='@{userdata.lastName}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/lastname"/>
</layout>
used:
dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User data=new User();//其他代码...
data.firstName.set("xxx");
binding.setUserdata(data);
//方式三 无模型非列表
xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data class=".dataclassname">
<import type="android.databinding.ObservableMap"/>
<variable name="prs" type="ObservableMap<String, Object>"/>
</data>
<TextView
android:text='@{prs["index"]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/lastname"/>
</layout>
used:
ObservableArrayMap<String, Object> prs = new ObservableArrayMap<>();
prs.put("index", String.valueOf(position));
binding.setPrs(prs);
//方式四 无模型简单列表
xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data class=".dataclassname">
<import type="android.databinding.ObservableList"/>
<variable name="xxx" type="ObservableList<Object>"/>
</data>
<TextView
android:text='@{xxx[0]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:text='@{xxx[1]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</layout>
used:
dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
ObservableArrayList<Object> user = new ObservableArrayList<>();
user.add("Google");
user.add("Inc.");
binding.setXxx(user);
3. 调用
1. 未知视图绑定类
dataclassname binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
dataclassname binding = DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent);
2. 已知视图绑定类
dataclassname binding = dataclassname.inflate(layoutInflater);
dataclassname binding = dataclassname.inflate(LayoutInflater, viewGroup, false);
dataclassname binding = dataclassname.bind(viewRoot);
4. 返回视图
dataclassname binding = dataclassname.inflate(LayoutInflater, viewGroup, false);
binding.getRoot();
# GestureDetector VelocityTracker 触摸手势 及 触摸速度
对屏幕的常用手势操作:
private GestureDetector gestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab);
gestureDetector = new GestureDetector(this, new GestureListener());
gestureDetector.setIsLongpressEnabled(false);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
// 继承于SimpleOnGestureListener,实现所有事件监听方法
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.i("2222", velocityX + "");
Log.i("2222", velocityY + "");
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.i("test", "doubletap");
return super.onDoubleTap(e);
}
}
对屏幕的触摸速度:
private VelocityTracker mVelocityTracker = null;
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if (mVelocityTracker == null)
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(event);
switch (action) {
case MotionEvent.ACTION_UP:
mVelocityTracker.computeCurrentVelocity(1000);//设置单位为毫秒
//移动像素距离
Log.i("11111", mVelocityTracker.getXVelocity(0) + "");
Log.i("11111", mVelocityTracker.getYVelocity(0) + "");
break;
}
return true;
}
# 图像资源 drawable
1. 缩放图片
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:scaleWidth="50%"
android:scaleHeight="50%"
android:drawable="@drawable/a6"
android:scaleGravity="center_vertical|center_horizontal"
>
</scale>
2. 旋转图片
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/a1"
android:visible="true"
android:fromDegrees="-90"
android:toDegrees="180"
android:pivotX="50%"
android:pivotY="50%"
>
</rotate>
3. 叠加图片
<?r circrsion="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval" >
<solid android:color="#FFACB8C3" />
</shape>
</item>
<item
android:bottom="2dp"
android:left="2dp"
android:right="2dp"
android:top="2dp">
<shape android:shape="oval">
<solid android:color="#FFbdcad6" />
</shape>
</item>
</layer-list>
4. 各种状态图片
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 默认时的背景图片-->
<item android:drawable="@drawable/a2" android:state_focused="false" android:state_pressed="false"/>
<!-- 按下时状态-->
<item android:drawable="@drawable/a" android:state_pressed="true"/>
<!--获得焦点时的图片背景-->
<item android:drawable="@drawable/a3" android:state_focused="true"/>
<!--无焦点状态-->
<item android:drawable="@drawable/a4" android:state_focused="false"/>
</selector>
<?xml version="1.0" encoding="utf-8" ?>
5. 选择图片显示
<?xml version="1.0" encoding="utf-8" ?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@drawable/a1"
android:maxLevel="0" />
<item
android:drawable="@drawable/a2"
android:maxLevel="1" />
</level-list>
代码修改显示
final ImageView imageView = (ImageView) findViewById(R.id.imgView);
imageView.setImageLevel(1);//默认的level为0,将到设置为1
//或 imageView.getDrawable().setLevel(1);
6. 部分显示
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/a1"
android:clipOrientation="horizontal"
android:gravity="left" />
代码修改显示
ImageView imageview = (ImageView) findViewById(R.id.image);
ClipDrawable drawable = (ClipDrawable) imageview.getDrawable();
drawable.setLevel(drawable.getLevel() + 1000);
7. 9 PNG
将图片命名为 **.9.png 放入 drawable 之后调整边框即可
8. 形状
shape 形状 如矩形等
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--
shape
android:shape=["rectangle" | "oval" | "line" | "ring"]
矩形(rectangle)、椭圆形(oval)、线性形状(line)、环形(ring)
-->
<!-- 实心 -->
<solid android:color="#ff9d77"/>
<!-- 渐变 -->
<gradient
android:startColor="#ff8c00"
android:endColor="#FFFFFF"
android:angle="270" />
<!-- 描边 -->
<stroke
android:width="2dp"
android:color="#dcdcdc" />
<!-- 圆角 -->
<corners
android:radius="2dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
环行实例
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadius="20dp"
android:thickness="50dp"
android:useLevel="false">
<!--
innerRadius 内部半径
innerRadiusRatio 内部半径比例 innerRadius 存在 此值无效
thickness 环厚度
thicknessRatio 环厚度比例 thickness 存在 此值无效
-->
<stroke android:width="10dp" android:color="#22ee0000" />
<!--
stroke 描边
-->
<solid android:color="#33ee0033"/>
<!--
solid 内容填
-->
</shape>
9. 偏移图片
<transition
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="-10dp" android:bottom="10dp" android:drawable="@drawable/a1" >
</item>
</transition>
10. 自定义图标SVG
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportWidth="1024"
android:viewportHeight="1024"
android:width="1024px"
android:height="1024px">
<!--pathData 放置 svg path 数据-->
<path android:fillColor="#963" android:pathData="M511.417227 536.082488l81.180927 0 0 60.886719-81.180927 0 0-60.886719Z" />
</vector>
# 动画 anim
补间动画 anim 文件夹
效果支持:
Alpha:淡入淡出效果
Scale:缩放效果
Rotate:旋转效果
Translate:移动效果
XML 文件通过 AnimationUtils.loadAnimation(Context, R.anim.**) 获取 XML示例
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="0" android:toXScale="5"
android:fromYScale="0" android:toYScale="5"
android:pivotX="50%" android:pivotY="50%"
android:duration="1000" />
</set>
使用
Animation animation = (Animation) AnimationUtils.loadAnimation(Context, R.anim.**);
代码里new对象 例如: AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
动画次数和方式
animation.setRepeatCount(Animation.INFINITE);
animation.setRepeatMode(Animation.RESTART);
动画事件 setAnimationListener 示例
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束
}
@Override
public void onAnimationRepeat(Animation animation) {
//重复动画事件
}
});
动画效果 AccelerateInterpolator ()
animation.setInterpolator(new AccelerateInterpolator());
布局动画
建立布局动画
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/list_anim"/>
<!-- android:animationOrder 执行循序 normal 顺序 random 随机 reverse 反向 -->
XML使用布局动画
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layoutAnimation="@anim/list_anim_layout"
>
代码建立及使用
Animation animation = (Animation) AnimationUtils.loadAnimation(
{Context}, R.anim.list_anim);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
controller.setDelay(0.5f);
listView.setLayoutAnimation(controller);
Activity 间切换 跳转之后调用 如 startActivity 之后
overridePendingTransition(android.R.anim.slide_in_left,android.R.anim.slide_out_right);
动画集
代码: 通过 AnimationSet 包含多个动画,使用 addAnimation 添加
AnimationSet animationset = new AnimationSet(true);
animationset.addAnimation(animation);
XML:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="0" android:toXScale="5"
android:fromYScale="0" android:toYScale="5"
android:pivotX="50%" android:pivotY="50%"
android:duration="1000" />
</set>
使用:
AnimationSet animationset = (AnimationSet) AnimationUtils.loadAnimation({Context}, R.anim.**);
使用动画: 调用view.startAnimation() 或 setAnimation()后在修改view内容
帧动画 anim 文件夹
建立帧
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/a_01" android:duration="50"/>
<item android:drawable="@drawable/a_02" android:duration="50"/>
<item android:drawable="@drawable/a_03" android:duration="50"/>
<item android:drawable="@drawable/a_04" android:duration="50"/>
<item android:drawable="@drawable/a_05" android:duration="50"/>
<item android:drawable="@drawable/a_06" android:duration="50"/>
</animation-list>
普遍view通过 setBackgroundResource
ImageView imageView= (ImageView)findViewById(R.id.image);
imageView.setBackgroundResource(R.anim.anim);
AnimationDrawable animationDrawable = (AnimationDrawable)
imageView.getBackground();
animationDrawable.start();
ImageView 还有 setImageResource
image.setImageResource(R.anim.li);
((AnimationDrawable)image.getDrawable()).start();
差值动画 animator 文件夹
代码建立
TextView text = (TextView) findViewById(R.id.textView1);
//根据属性的类型不同来调用 ofFloat ofInt ofArgb 等函数
ObjectAnimator oa= ObjectAnimator.ofFloat(text,"TextSize",60,5);
oa.setDuration(1000);
oa.start();
XML文件建立
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100"
android:propertyName="TextSize"
android:valueTo="60"
android:valueFrom="20"
android:valueType="floatType">
</objectAnimator>
调用
ObjectAnimator obj = (ObjectAnimator) AnimatorInflater.loadAnimator({Context}, R.animator.ts);
TextView text = (TextView) findViewById(R.id.textView1);
obj.setTarget(text);
obj.start();
动画集
代码: 通过 AnimationSet 包含多个动画,使用 addAnimation 添加
AnimationSet animationset = new AnimationSet(true);
animationset.addAnimation(animation);
XML:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100"
android:propertyName="TextSize"
android:valueTo="60"
android:valueFrom="20"
android:valueType="floatType">
</objectAnimator>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100"
android:propertyName="Height"
android:valueTo="60"
android:valueType="intType">
</objectAnimator>
</set>
使用:
AnimatorSet obj = (AnimatorSet) AnimatorInflater.loadAnimator({Context}, R.animator.**);
TextView text = (TextView) findViewById(R.id.textView1);
obj.setTarget(text);
obj.start();
# 挂件 Widget
1. 在 AndroidManifest 注册
.activity.TouchActivity$myreceiver 继承自 AppWidgetProvider的类
@xml/aa Widget 的配置文件
<receiver android:name=".activity.TouchActivity$myreceiver" android:label="@string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/aa" />
</receiver>
2. 配置文件
@layout/aa 指定布局文件
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="146dip" android:minHeight="72dip" android:initialLayout="@layout/aa">
</appwidget-provider>
3. 实现 AppWidgetProvider的类
public static class myreceiver extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
//定期更新对象,如实现动画等
Timer timer = new Timer();
timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1, 1000);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public class MyTime extends TimerTask {
RemoteViews remoteViews;
AppWidgetManager appWidgetManager;
ComponentName thisWidget;
DateFormat format = SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault());
public MyTime(Context context, AppWidgetManager appWidgetManager) {
this.appWidgetManager = appWidgetManager;
//建立视图
remoteViews = new RemoteViews(context.getPackageName(), R.layout.aa);
//往指定包里查找视图
thisWidget = new ComponentName(context, myreceiver.class);
}
@Override
public void run() {
//修改视图
remoteViews.setTextViewText(R.id.text_content, "Time = " + format.format(new Date()));
//重新设置视图
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
}
}
# 网页 WebView
于JS交互绑定在JS的window对象中
final WebView vw = new WebView(this);
vw.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
//需重写各种JS事件才能实现各种JS的方法
AlertDialog.Builder alert = new AlertDialog.Builder(TouchActivity.this);
alert.setTitle("Alert");
alert.setMessage(message);
alert.show();
return super.onJsAlert(view, url, message, result);
}
});
vw.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
//调用JS方法
vw.loadUrl("javascript:hiandroid()");
}
});
vw.addJavascriptInterface(new Object() {
@JavascriptInterface
public String alert(String string) {
//JS调用方法
AlertDialog.Builder alert = new AlertDialog.Builder(TouchActivity.this);
alert.setMessage(string);
alert.show();
return "HI";
}
}, "dome");
vw.getSettings().setJavaScriptEnabled(true);
vw.loadUrl("http://www.urltest.tk/a.html");
setContentView(vw);
# 定时器 Alarm
设置时间已超过,将立即触发
AlarmManager al= (AlarmManager)getSystemService(ALARM_SERVICE);
Intent it= new Intent(MyActivity.MY_ACTION);
PendingIntent pi=PendingIntent.getActivity(this,0,it,0);
//AlarmManager.RTC; //指定时间,System.currentTimeMillis()+N毫秒 激活时不唤醒
//AlarmManager.RTC_WAKEUP //指定时间,System.currentTimeMillis()+N毫秒 激活时唤醒
//AlarmManager.ELAPSED_REALTIME;//开机时间+N毫秒 激活时不唤醒
//AlarmManager.ELAPSED_REALTIME_WAKEUP; //开机时间+N毫秒 激活时唤醒
al.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, pi);
//重复触发
//al.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,10000,pi);
//按系统预定义重复触发 AlarmManager.INTERVAL_*
//al.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+10000,AlarmManager.INTERVAL_DAY,pi);
# 广播 Broadcast Receiver
//常量
public final static String MYINTERFER = "myfilterkey";
1. 注册
a. 代码注册
IntentFilter intentfilter = new IntentFilter(MYINTERFER);
BroadcastReceiver myreceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//不要做长时间处理操作
Toast.makeText(context,"msg",Toast.LENGTH_LONG).show();
}
};
registerReceiver(myreceiver,intentfilter);
b. AndroidManifest注册 (如果是内部类,加 static !!!应用未启动可用!!!)
public class myreceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//不要做长时间处理操作
Toast.makeText(context,"msg",Toast.LENGTH_LONG).show();
}
}
AndroidManifest:
<receiver android:name=".activity.TouchActivity$myreceiver">
<intent-filter>
<action android:name="myfilterkey" />
</intent-filter>
</receiver>
2. 发送
Intent intent = new Intent(TouchActivity.MYINTERFER);
sendBroadcast(intent);
3. 本地广播
LocalBroadcastManager localbcm = LocalBroadcastManager.getInstance(this);
localbcm.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//处理本地广播
}
},new IntentFilter(TouchActivity.MYINTERFER));
localbcm.sendBroadcast(new Intent(TouchActivity.MYINTERFER));
4. 有序广播 sendOrderedBroadcast(new Intent(TouchActivity.MYINTERFER),"权限字符串");
5. 可覆盖广播,会覆盖成最后一个值 sendStickyBroadcast(new Intent(TouchActivity.MYINTERFER));
6. 示例 (处理下载)
String url = "http://dlsw.baidu.com/sw-search-sp/soft/6c/23675/Photoshop_CS6.3510481888.7z";
Uri uri = Uri.parse(url);
DownloadManager download = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);//只在WIFI下下载
final long enqueue = download.enqueue(request);
//还有其他事件等等
IntentFilter interf = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
BroadcastReceiver br = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long downid = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (downid == enqueue) {
//your download
}
}
};
registerReceiver(br, interf);
# 服务 Service (长时间执行代码)
1. 服务可加权限,供其他程序调用
2. 服务可以在 Activity,Broadcast Receiver 等启动
3. 服务的Activity交互通过 bindService 的 ServiceConnection (IBinder service) 进行
5. 在服务中可通过回调来处理视图
6. 服务处理过程: 创建和绑定
7. 回调用 Handler 处理或自定义回调函数,如下示例:
a. 服务添加
//创建
public static class myservice extends Service{
private IBinder binder=new myservice.LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public void onCreate() {
super.onCreate();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
if(h!=null){
Message msg= new Message();
Bundle b=new Bundle();
b.putString("hehe", "Date:" + new Date().toString());
msg.setData(b);
h.sendMessage(msg);
}
}
}, 0, 1000);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//开始执行 根据返回值不同,可能会有多次调用
return START_STICKY;
}
@Override
public void onDestroy() {
//开始结束
super.onDestroy();
}
public class LocalBinder extends Binder {
public LocalBinder() {
super();
}
public myservice get_service(){
return myservice.this;
}
}
Handler h;
public void sethandle(Handler h){
this.h=h;
}
}
//启动
Intent intent = new Intent(this,myservice.class);
startService(intent);
b. 服务绑定 在 Activity 中
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myservice localser=((myservice.LocalBinder)service).get_service();
localser.sethandle(h);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
},BIND_AUTO_CREATE);
8. Service 多次启动请求处理之类 IntentService 处理多个请求服务,任务完成会终结自己
重写 onHandleIntent 方法即可 Intent 为请求的Intent,主要用于多个类同的服务请求
# 资源接口 Content Provider
1. Uri 使用
Uri muri = Uri.parse("content://www.urltest.tk/people/111");
UriMatcher match = new UriMatcher(UriMatcher.NO_MATCH);
match.addURI("www.urltest.tk", "people/#", 1);
switch (match.match(muri)) {
case 1:
//匹配进这里
break;
default:
break;
}
//Uri 解析ID 和添加ID
long id=ContentUris.parseId(muri);
ContentUris.withAppendedId(muri,111);
//Uri 处理路径
Uri.withAppendedPath("content://www.urltest.tk","people"); => Uri.parse("content://www.urltest.tk/people")
2. Uri 注册 provider provider实现见:3
<provider android:name=".activity.TouchActivity$myconentp"
android:authorities="www.urltest.tk"
android:multiprocess="false"
>
</provider>
3. 实现示例
public static class myconentp extends ContentProvider{
private static String TAG="provider";
public static final String AUTHORITY = "www.urltest.tk";
public static final int PEOPLES = 1;
public static final int PEOPLE = 2;
public static final UriMatcher match;
static {
match = new UriMatcher(UriMatcher.NO_MATCH);
match.addURI(AUTHORITY, "people", PEOPLES);
match.addURI(AUTHORITY, "people/#", PEOPLE);
}
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/www.urltest.tk";
public static final String CONTENT_TYPE_ITME = "vnd.android.cursor.item/www.urltest.tk";
@Override
public boolean onCreate() {
Log.i(TAG,"create");
return true;
}
@Nullable
@Override
public String getType(Uri uri) {
switch (match.match(uri)) {
case PEOPLES:
return CONTENT_TYPE;
case PEOPLE:
return CONTENT_TYPE_ITME;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
//projection 字段列表
//selection WHERE 条件
//selectionArgs WHERE 绑定数据
//sortOrder 排序
Log.i(TAG, "query");
switch (match.match(uri)) {
case PEOPLE://单个查询
long id=ContentUris.parseId(uri);//解析到ID
break;
case PEOPLES://批量查询
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
//values 新值
switch (match.match(uri)) {
case PEOPLES:
//进行添加操作
String title=values.getAsString("title");
Log.i(TAG, "insert:" + title);
long insert_id=100;
return ContentUris.withAppendedId(uri,insert_id);
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
//selection WHERE 条件
//selectionArgs WHERE 绑定数据
switch (match.match(uri)) {
case PEOPLES:
Log.i(TAG, "delete");
//执行删除操作
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
return 1;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
//values 新值
//selection WHERE 条件
//selectionArgs WHERE 绑定数据
switch (match.match(uri)) {
case PEOPLES:
Log.i(TAG, "update");
//进行更新操作
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
return 0;
}
}
4. 使用
Uri uri = Uri.parse("content://www.urltest.tk/people");
ContentResolver cr = getContentResolver();
//增
ContentValues cv = new ContentValues();
cv.put("title", "title");
Uri insert_uri=cr.insert(uri, cv);
long insert_id=ContentUris.parseId(insert_uri);
Log.i(TAG, "INSERTID:" + insert_id);
//删
cr.delete(uri, "id=?", new String[]{"1"});
//改
cv.put("title", "newtitle");
cr.update(uri, cv, "id=" + insert_id, new String[]{String.valueOf(insert_id)});
//查
Cursor all_rs = cr.query(uri,null,null,null,null);
if(all_rs!=null) {
while (all_rs.moveToNext()) {
String title = all_rs.getString(all_rs.getColumnIndex("title"));
}
}
Uri uriitem = Uri.parse("content://www.urltest.tk/people/111");
Cursor item_rs = cr.query(uriitem, null, null, null, null);
if(item_rs!=null){
String title=all_rs.getString(item_rs.getColumnIndex("title"));
}
5. 本地资源存储
a. 数据库 SQLite
class myDBHelp extends SQLiteOpenHelper{
public myDBHelp(Context context, String name, SQLiteDatabase.CursorFactory factory,
int version) {
super(context, name, factory, version);
}
public myDBHelp(Context context, String name, int version) {
this(context, name, null, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
//初始化数据库
db.execSQL("create table mytable("
+" id INTEGER PRIMARY KEY autoincrement,"
+ " title varchar(20)"
+");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//升级数据库
}
}
使用
myDBHelp dbhelp= new myDBHelp(this,"db_name",5);
SQLiteDatabase db = dbhelp.getWritableDatabase();
//增
ContentValues insval = new ContentValues();
insval.put("title", "title");
long id = db.insert("mytable", null, insval);
//改
insval.put("title", "newtitle");
db.update("mytable",insval , "id=?",new String[]{String.valueOf(id)} );
//查
Cursor db_rs = db.query("mytable", new String[]{"title"},null, null, null, null, null);
if(db_rs!=null) {
while (db_rs.moveToNext()) {
String title = db_rs.getString(db_rs.getColumnIndex("title"));
Log.i(TAG,title);
}
}
//删
db.delete("mytable", "id=?", new String[]{String.valueOf(id)});
b. 键值对 SharedPreferences 示例
SharedPreferences mySharedPreferences= getSharedPreferences("test", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = mySharedPreferences.edit();
editor.putString("name", "Karl");
editor.commit();
String name=mySharedPreferences.getString("name","unkown");
Log.i("myout",name);
c. 文件
try {
String msg="hi";
String file="message.txt";
FileOutputStream fos = openFileOutput(file,
MODE_APPEND);
fos.write(msg.getBytes());
fos.close();
FileInputStream inStream = this.openFileInput(file);
byte[] buffer = new byte[1024];
int hasRead = 0;
StringBuilder sb = new StringBuilder();
while ((hasRead = inStream.read(buffer)) != -1) {
sb.append(new String(buffer, 0, hasRead));
}
inStream.close();
Log.i("myout",sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
d. SD卡文件
缓存文件夹 getCacheDir(); getExternalCacheDir()
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String filename="filename.txt";
String msg="this is txt";
File file = new File(Environment.getExternalStorageDirectory()
.toString()
+ File.separator
+ filename);
if (!file.getParentFile().exists()) { // 父文件夹不存在
file.getParentFile().mkdirs(); // 创建文件夹
}
PrintStream out = null; // 打印流对象用于输出
try {
out = new PrintStream(new FileOutputStream(file, true)); // 追加文件
out.println(msg);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close(); // 关闭打印流
}
}
Scanner scan = null; // 扫描输入
StringBuilder sb = new StringBuilder();
try {
scan = new Scanner(new FileInputStream(file)); // 实例化Scanner
while (scan.hasNext()) { // 循环读取
sb.append(scan.next()); // 设置文本
}
Log.i("myout",sb.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (scan != null) {
scan.close(); // 关闭打印流
}
}
} else {
// SDCard不存在,使用Toast提示用户
}
# 提醒 Notification
//常量
public final static int TAG = 1;
1. API 11 后示例
PendingIntent pendingIntent2 = PendingIntent.getActivity(this, 0,
new Intent(this, TouchActivity.class), 0);
Notification notify2 = new Notification.Builder(this)
.setSmallIcon(R.drawable.abc_btn_check_to_on_mtrl_015)
.setTicker("TickerText:" + "您有新短消息,请注意查收!")
.setContentTitle("Notification Title")
.setContentText("This is the notification message")
.setContentIntent(pendingIntent2)
.setNumber(1)
.getNotification(); // 需要注意build()是在API level
// 16及之后增加的,在API11中可以使用getNotificatin()来代替
notify2.flags |= Notification.FLAG_AUTO_CANCEL;
manager.notify(TAG, notify2);
2. API 16 后示例
PendingIntent pendingIntent3 = PendingIntent.getActivity(this, 0,
new Intent(this, TouchActivity.class), 0);
Notification notify3 = new Notification.Builder(this)
.setSmallIcon(R.drawable.notification_template_icon_bg)
.setTicker("TickerText:" + "您有新短消息,请注意查收!")
.setContentTitle("Notification Title")
.setContentText("This is the notification message")
.setContentIntent(pendingIntent3).setNumber(1).build();
notify3.flags |= Notification.FLAG_AUTO_CANCEL; // FLAG_AUTO_CANCEL表明当通知被用户点击时,通知将被清除。
manager.notify(TAG, notify3);
3. 自定义提醒视图 (Deprecated)
Notification myNotify = new Notification();
myNotify.icon = R.drawable.notification_template_icon_bg;
myNotify.tickerText = "TickerText:您有新短消息,请注意查收!";
myNotify.when = System.currentTimeMillis();
myNotify.flags = Notification.FLAG_NO_CLEAR;// 不能够自动清除
RemoteViews rv = new RemoteViews(getPackageName(),
R.layout.aa);
rv.setTextViewText(R.id.text_content, "hello wrold!");
myNotify.contentView = rv;
Intent intent = new Intent(Intent.ACTION_MAIN);
PendingIntent contentIntent = PendingIntent.getActivity(this, 1,
intent, 1);
myNotify.contentIntent = contentIntent;
manager.notify(TAG, myNotify);
4. 关闭提醒
manager.cancel(TAG);