依赖关系在 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);