Android高手进阶教程(二十六)之---Android超仿Path菜单的实现!
来源:互联网 发布:三星手机数据恢复 编辑:程序博客网 时间:2024/05/29 02:38
Hi~大家好,出来创业快3个月了,一切还不错,前一段时间用了业余时间搞了个问答类网站YQMA(http://yqma.net).想做中国的stackoverflow,哈哈,只是YY下,希望大家多多支持!
好了,今天给大家分享的是Path菜单的简单实现,可以支持自定义方向(左上,右上,右下,左下),并且可以自定义菜单的个数,难点就是菜单的摆放位置(动态设置margin),还有动画的实现,其实动画只是简单用了个TranslateAnimation,N个菜单一起移动的时候感觉很cool~
这里也用到了自定义标签,这里不懂的童鞋可以看我 Android高手进阶教程(四)之----Android 中自定义属性(attr.xml,TypedArray)的使用!这篇文章.好了废话不多说了,
首先创建一个android工程命名为PathTest.目录结构如下图:
第二步:在values文件夹下新建一个attrs.xml文件,代码如下:
- <?xmlversion="1.0"encoding="utf-8"?>
- <resources>
- <declare-styleablename="PathMenuView">
- <attrname="position">
- <enumname="left_top"value="0"></enum>
- <enumname="right_top"value="1"></enum>
- <enumname="right_bottom"value="2"></enum>
- <enumname="left_bottom"value="3"></enum>
- </attr>
- </declare-styleable>
- </resources>
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="PathMenuView"> <attr name="position"> <enum name="left_top" value="0"></enum> <enum name="right_top" value="1"></enum> <enum name="right_bottom" value="2"></enum> <enum name="left_bottom" value="3"></enum> </attr> </declare-styleable> </resources>
第三步:新建一个PathMenuView.java这个就是我们自定义的Path菜单控件,代码如下:
- package com.tutor.path;
- import android.content.Context;
- import android.content.res.TypedArray;
- import android.util.AttributeSet;
- import android.view.Gravity;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.animation.Animation;
- import android.view.animation.AnticipateInterpolator;
- import android.view.animation.OvershootInterpolator;
- import android.view.animation.TranslateAnimation;
- import android.widget.FrameLayout;
- import android.widget.ImageView;
- /**
- * @author frankiewei.
- * 超级仿path菜单
- * position定义菜单的位置,目前支持:左上;右上;右下;左下四个方向。
- * menuResIds定义出现的菜单的资源ID
- */
- public class PathMenuViewextends FrameLayout {
- private staticfinal int LEFT_TOP =0;
- private staticfinal int RIGHT_TOP =1;
- private staticfinal int RIGHT_BOTTOM =2;
- private staticfinal int LEFT_BOTTOM =3;
- /**
- * 默认的位置是在右下角.
- */
- private int position =3;
- /**
- * 那个圆形菜单.
- */
- private ImageView mHome;
- /**
- * 上下文.
- */
- private Context mContext;
- /**
- * 设备的宽度.
- */
- private int mWIDTH =0;
- /**
- * 设备的高度.
- */
- private int mHEIGHT =0;
- /**
- * 设备的density.
- */
- private float mDensity;
- /**
- * 菜单是否显示.
- */
- private boolean bMenuShow;
- private staticint xOffset = 15;
- private staticint yOffset = -13;
- /**
- * 菜单的资源个数.
- */
- private int[] menuResIds = {R.drawable.composer_camera,R.drawable.composer_music,
- R.drawable.composer_sleep,R.drawable.composer_music,R.drawable.composer_place};
- public PathMenuView(Context context){
- super(context);
- setupViews();
- }
- public PathMenuView(Context context, AttributeSet attrs) {
- super(context, attrs);
- TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.PathMenuView);
- position = a.getInt(R.styleable.PathMenuView_position,3);
- a.recycle();
- setupViews();
- }
- private void setupViews(){
- mContext = getContext();
- mHEIGHT = mContext.getResources().getDisplayMetrics().heightPixels;
- mWIDTH = mContext.getResources().getDisplayMetrics().widthPixels;
- mDensity = mContext.getResources().getDisplayMetrics().density;
- xOffset = (int) (10.667 * mDensity);
- yOffset = (int) (8.667 * mDensity);
- mHome = new ImageView(mContext);
- mHome.setImageResource(R.drawable.composer_button);
- mHome.setOnClickListener(listener);
- addView(mHome);
- LayoutParams mHomeparams = (FrameLayout.LayoutParams)mHome.getLayoutParams();
- mHomeparams.width = LayoutParams.WRAP_CONTENT;
- mHomeparams.height = LayoutParams.WRAP_CONTENT;
- switch (position) {
- case LEFT_TOP:
- mHomeparams.gravity = Gravity.LEFT | Gravity.TOP;
- for (int i =0; i < menuResIds.length; i++) {
- int width_padding = mWIDTH / ((menuResIds.length -1) * 2);
- int height_padding = mHEIGHT / ((menuResIds.length -1) * 2);
- ImageView imageView = new ImageView(mContext);
- imageView.setImageResource(menuResIds[i]);
- addView(imageView);
- LayoutParams params = (FrameLayout.LayoutParams) imageView
- .getLayoutParams();
- params.width = LayoutParams.WRAP_CONTENT;
- params.height = LayoutParams.WRAP_CONTENT;
- params.leftMargin = mWIDTH / 2
- - ((menuResIds.length - i - 1) * width_padding);
- params.topMargin = mHEIGHT / 2 - i * height_padding;
- params.gravity = Gravity.LEFT | Gravity.TOP;
- imageView.setLayoutParams(params);
- }
- break;
- case RIGHT_TOP:
- mHomeparams.gravity = Gravity.RIGHT | Gravity.TOP;
- for (int i =0; i < menuResIds.length; i++) {
- int width_padding = mWIDTH / ((menuResIds.length -1) * 2);
- int height_padding = mHEIGHT / ((menuResIds.length -1) * 2);
- ImageView imageView = new ImageView(mContext);
- imageView.setImageResource(menuResIds[i]);
- addView(imageView);
- LayoutParams params = (FrameLayout.LayoutParams) imageView
- .getLayoutParams();
- params.width = LayoutParams.WRAP_CONTENT;
- params.height = LayoutParams.WRAP_CONTENT;
- params.rightMargin = mWIDTH / 2
- - ((menuResIds.length - i - 1) * width_padding);
- params.topMargin = mHEIGHT / 2 - i * height_padding;
- params.gravity = Gravity.RIGHT | Gravity.TOP;
- imageView.setLayoutParams(params);
- }
- break;
- case RIGHT_BOTTOM:
- mHomeparams.gravity = Gravity.RIGHT | Gravity.BOTTOM;
- for (int i =0; i < menuResIds.length; i++) {
- int width_padding = mWIDTH / ((menuResIds.length -1) * 2);
- int height_padding = mHEIGHT / ((menuResIds.length -1) * 2);
- ImageView imageView = new ImageView(mContext);
- imageView.setImageResource(menuResIds[i]);
- addView(imageView);
- LayoutParams params = (FrameLayout.LayoutParams) imageView
- .getLayoutParams();
- params.width = LayoutParams.WRAP_CONTENT;
- params.height = LayoutParams.WRAP_CONTENT;
- params.rightMargin = mWIDTH / 2
- - ((menuResIds.length - i - 1) * width_padding);
- params.bottomMargin = mHEIGHT / 2 - i * height_padding;
- params.gravity = Gravity.RIGHT | Gravity.BOTTOM;
- imageView.setLayoutParams(params);
- }
- break;
- case LEFT_BOTTOM:
- mHomeparams.gravity = Gravity.LEFT | Gravity.BOTTOM;
- for(int i =0; i < menuResIds.length; i++){
- int width_padding = mWIDTH / ((menuResIds.length -1) * 2);
- int height_padding = mHEIGHT / ((menuResIds.length -1) *2);
- ImageView imageView = new ImageView(mContext);
- imageView.setImageResource(menuResIds[i]);
- addView(imageView);
- LayoutParams params = (FrameLayout.LayoutParams)imageView.getLayoutParams();
- params.width = LayoutParams.WRAP_CONTENT;
- params.height = LayoutParams.WRAP_CONTENT;
- params.leftMargin = mWIDTH / 2 - ((menuResIds.length - i -1) * width_padding);
- params.bottomMargin = mHEIGHT / 2 - i * height_padding;
- params.gravity = Gravity.LEFT | Gravity.BOTTOM;
- imageView.setLayoutParams(params);
- }
- break;
- default:
- break;
- }
- mHome.setLayoutParams(mHomeparams);
- }
- private OnClickListener listener =new OnClickListener() {
- public void onClick(View v) {
- if (!bMenuShow) {
- startAnimationIn(PathMenuView.this,300);
- } else {
- startAnimationOut(PathMenuView.this,300);
- }
- bMenuShow = !bMenuShow;
- }
- };
- /**
- * 菜单隐藏动画.
- *
- * @param group
- * @param duration
- */
- private void startAnimationIn(ViewGroup group,int duration) {
- for (int i =1; i < group.getChildCount(); i++) {
- ImageView imageview = (ImageView) group.getChildAt(i);
- imageview.setVisibility(0);
- MarginLayoutParams mlp = (MarginLayoutParams) imageview
- .getLayoutParams();
- Animation animation = null;
- switch (position) {
- case LEFT_TOP:
- animation = new TranslateAnimation(0F,-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset);
- break;
- case RIGHT_TOP:
- animation = new TranslateAnimation(mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset,0F);
- break;
- case LEFT_BOTTOM:
- animation = new TranslateAnimation(0F, -mlp.leftMargin+ xOffset, 0F, -yOffset + mlp.bottomMargin);
- break;
- case RIGHT_BOTTOM:
- animation = new TranslateAnimation(mlp.rightMargin-xOffset,0F,-yOffset + mlp.bottomMargin, 0F);
- break;
- default:
- break;
- }
- animation.setFillAfter(true);
- animation.setDuration(duration);
- animation.setStartOffset((i * 100) / (-1 + group.getChildCount()));
- animation.setInterpolator(new OvershootInterpolator(2F));
- imageview.startAnimation(animation);
- }
- }
- /**
- * 菜单显示动画.
- *
- * @param group
- * @param duration
- */
- private void startAnimationOut(ViewGroup group,int duration){
- for (int i =1; i < group.getChildCount(); i++) {
- final ImageView imageview = (ImageView) group
- .getChildAt(i);
- MarginLayoutParams mlp = (MarginLayoutParams) imageview.getLayoutParams();
- Animation animation = null;
- switch (position) {
- case LEFT_TOP:
- animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset,0F);
- break;
- case RIGHT_TOP:
- animation = new TranslateAnimation(0F,mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset);
- break;
- case LEFT_BOTTOM:
- animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F, -yOffset + mlp.bottomMargin,0F);
- break;
- case RIGHT_BOTTOM:
- animation = new TranslateAnimation(0F,mlp.rightMargin-xOffset, 0F,-yOffset + mlp.bottomMargin);
- break;
- default:
- break;
- }
- animation.setFillAfter(true);animation.setDuration(duration);
- animation.setStartOffset(((group.getChildCount()-i) * 100)
- / (-1 + group.getChildCount()));
- animation.setInterpolator(new AnticipateInterpolator(2F));
- imageview.startAnimation(animation);
- }
- }
- }
package com.tutor.path;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.view.Gravity;import android.view.View;import android.view.ViewGroup;import android.view.animation.Animation;import android.view.animation.AnticipateInterpolator;import android.view.animation.OvershootInterpolator;import android.view.animation.TranslateAnimation;import android.widget.FrameLayout;import android.widget.ImageView;/** * @author frankiewei. * 超级仿path菜单 * position定义菜单的位置,目前支持:左上;右上;右下;左下四个方向。 * menuResIds定义出现的菜单的资源ID */public class PathMenuView extends FrameLayout {private static final int LEFT_TOP = 0;private static final int RIGHT_TOP = 1;private static final int RIGHT_BOTTOM = 2;private static final int LEFT_BOTTOM = 3;/** * 默认的位置是在右下角. */private int position = 3;/** * 那个圆形菜单. */private ImageView mHome;/** * 上下文. */private Context mContext;/** * 设备的宽度. */private int mWIDTH = 0;/** * 设备的高度. */private int mHEIGHT = 0;/** * 设备的density. */private float mDensity;/** * 菜单是否显示. */private boolean bMenuShow;private static intxOffset= 15;private static intyOffset= -13;/** * 菜单的资源个数. */private int[] menuResIds = {R.drawable.composer_camera,R.drawable.composer_music,R.drawable.composer_sleep,R.drawable.composer_music,R.drawable.composer_place};public PathMenuView(Context context){super(context);setupViews();}public PathMenuView(Context context, AttributeSet attrs) {super(context, attrs);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PathMenuView);position = a.getInt(R.styleable.PathMenuView_position,3);a.recycle();setupViews();}private void setupViews(){mContext = getContext();mHEIGHT = mContext.getResources().getDisplayMetrics().heightPixels;mWIDTH = mContext.getResources().getDisplayMetrics().widthPixels;mDensity = mContext.getResources().getDisplayMetrics().density;xOffset = (int) (10.667 * mDensity);yOffset = (int) (8.667 * mDensity);mHome = new ImageView(mContext);mHome.setImageResource(R.drawable.composer_button);mHome.setOnClickListener(listener);addView(mHome);LayoutParams mHomeparams = (FrameLayout.LayoutParams)mHome.getLayoutParams();mHomeparams.width = LayoutParams.WRAP_CONTENT;mHomeparams.height = LayoutParams.WRAP_CONTENT;switch (position) {case LEFT_TOP:mHomeparams.gravity = Gravity.LEFT | Gravity.TOP;for (int i = 0; i < menuResIds.length; i++) {int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2);ImageView imageView = new ImageView(mContext);imageView.setImageResource(menuResIds[i]);addView(imageView);LayoutParams params = (FrameLayout.LayoutParams) imageView.getLayoutParams();params.width = LayoutParams.WRAP_CONTENT;params.height = LayoutParams.WRAP_CONTENT;params.leftMargin = mWIDTH / 2- ((menuResIds.length - i - 1) * width_padding);params.topMargin = mHEIGHT / 2 - i * height_padding;params.gravity = Gravity.LEFT | Gravity.TOP;imageView.setLayoutParams(params);}break;case RIGHT_TOP:mHomeparams.gravity = Gravity.RIGHT | Gravity.TOP;for (int i = 0; i < menuResIds.length; i++) {int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2);ImageView imageView = new ImageView(mContext);imageView.setImageResource(menuResIds[i]);addView(imageView);LayoutParams params = (FrameLayout.LayoutParams) imageView.getLayoutParams();params.width = LayoutParams.WRAP_CONTENT;params.height = LayoutParams.WRAP_CONTENT;params.rightMargin = mWIDTH / 2- ((menuResIds.length - i - 1) * width_padding);params.topMargin = mHEIGHT / 2 - i * height_padding;params.gravity = Gravity.RIGHT | Gravity.TOP;imageView.setLayoutParams(params);}break;case RIGHT_BOTTOM:mHomeparams.gravity = Gravity.RIGHT | Gravity.BOTTOM;for (int i = 0; i < menuResIds.length; i++) {int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);int height_padding = mHEIGHT / ((menuResIds.length - 1) * 2);ImageView imageView = new ImageView(mContext);imageView.setImageResource(menuResIds[i]);addView(imageView);LayoutParams params = (FrameLayout.LayoutParams) imageView.getLayoutParams();params.width = LayoutParams.WRAP_CONTENT;params.height = LayoutParams.WRAP_CONTENT;params.rightMargin = mWIDTH / 2- ((menuResIds.length - i - 1) * width_padding);params.bottomMargin = mHEIGHT / 2 - i * height_padding;params.gravity = Gravity.RIGHT | Gravity.BOTTOM;imageView.setLayoutParams(params);}break;case LEFT_BOTTOM:mHomeparams.gravity = Gravity.LEFT | Gravity.BOTTOM;for(int i = 0; i < menuResIds.length; i++){int width_padding = mWIDTH / ((menuResIds.length - 1) * 2);int height_padding = mHEIGHT / ((menuResIds.length -1) * 2); ImageView imageView = new ImageView(mContext);imageView.setImageResource(menuResIds[i]);addView(imageView);LayoutParams params = (FrameLayout.LayoutParams)imageView.getLayoutParams();params.width = LayoutParams.WRAP_CONTENT;params.height = LayoutParams.WRAP_CONTENT;params.leftMargin = mWIDTH / 2 - ((menuResIds.length - i - 1) * width_padding);params.bottomMargin = mHEIGHT / 2 - i * height_padding;params.gravity = Gravity.LEFT | Gravity.BOTTOM;imageView.setLayoutParams(params);}break;default:break;}mHome.setLayoutParams(mHomeparams);}private OnClickListener listener = new OnClickListener() {public void onClick(View v) {if (!bMenuShow) {startAnimationIn(PathMenuView.this, 300);} else {startAnimationOut(PathMenuView.this, 300);}bMenuShow = !bMenuShow;}};/** * 菜单隐藏动画. * * @param group * @param duration */private void startAnimationIn(ViewGroup group, int duration) {for (int i = 1; i < group.getChildCount(); i++) {ImageView imageview = (ImageView) group.getChildAt(i);imageview.setVisibility(0);MarginLayoutParams mlp = (MarginLayoutParams) imageview.getLayoutParams();Animation animation = null;switch (position) {case LEFT_TOP:animation = new TranslateAnimation(0F,-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset);break;case RIGHT_TOP:animation = new TranslateAnimation(mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset,0F);break;case LEFT_BOTTOM:animation = new TranslateAnimation(0F, -mlp.leftMargin+ xOffset, 0F, -yOffset + mlp.bottomMargin);break;case RIGHT_BOTTOM:animation = new TranslateAnimation(mlp.rightMargin-xOffset,0F,-yOffset + mlp.bottomMargin, 0F);break;default:break;}animation.setFillAfter(true);animation.setDuration(duration);animation.setStartOffset((i * 100) / (-1 + group.getChildCount()));animation.setInterpolator(new OvershootInterpolator(2F));imageview.startAnimation(animation);}}/** * 菜单显示动画. * * @param group * @param duration */private void startAnimationOut(ViewGroup group,int duration){for (int i = 1; i < group.getChildCount(); i++) {final ImageView imageview = (ImageView) group.getChildAt(i);MarginLayoutParams mlp = (MarginLayoutParams) imageview.getLayoutParams();Animation animation = null;switch (position) {case LEFT_TOP:animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F,-mlp.topMargin + yOffset,0F);break;case RIGHT_TOP:animation = new TranslateAnimation(0F,mlp.rightMargin - xOffset,0F,-mlp.topMargin + yOffset);break;case LEFT_BOTTOM:animation = new TranslateAnimation(-mlp.leftMargin+xOffset,0F, -yOffset + mlp.bottomMargin,0F);break;case RIGHT_BOTTOM:animation = new TranslateAnimation(0F,mlp.rightMargin-xOffset, 0F,-yOffset + mlp.bottomMargin);break;default:break;}animation.setFillAfter(true);animation.setDuration(duration);animation.setStartOffset(((group.getChildCount()-i) * 100)/ (-1 + group.getChildCount()));animation.setInterpolator(new AnticipateInterpolator(2F));imageview.startAnimation(animation);}}}
第四步:PathTestActivity.java以及用到的布局文件main.xml代码如下:
PathTestActivity.java(基本没修改代码)代码如下:
- package com.tutor.path;
- import android.app.Activity;
- import android.os.Bundle;
- public class PathTestActivityextends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- }
package com.tutor.path;import android.app.Activity;import android.os.Bundle;public class PathTestActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }}
main.xml代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tutor="http://schemas.android.com/apk/res/com.tutor.path"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <com.tutor.path.PathMenuView
- android:id="@+id/text"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- tutor:position="right_bottom"
- />
- </LinearLayout>
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tutor="http://schemas.android.com/apk/res/com.tutor.path" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <com.tutor.path.PathMenuView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="fill_parent" tutor:position="right_bottom" /></LinearLayout>
运行点击效果如下:
图1:默认是在右下方这里menuResIds定义了五个菜单 图2:点击红色菜单,菜单收回.
下面我们修改main.xml的tutor属性为left_bottom,并且修改PathMenuView.java中的menuResIds.
- tutor:position="left_bottom"
tutor:position="left_bottom"
效果如下:
图3:自定义在左下角,六个菜单。
好了,今天就讲到这里了,菜单的圆弧不是很圆哈,凑合着学习,我也来无耻下,如果想要源代码的,可以去我的http://www.yqma.net注册一个用户,并且提一个问题,或者回答一个问题,我会把源代码发到你的邮箱里!谢谢!
- Android高手进阶教程(二十六)之---Android超仿Path菜单的实现!
- Android高手进阶教程(二十六)之---Android超仿Path菜单的实现!
- Android高手进阶教程(二十六)之---Android超仿Path菜单的实现!
- Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- Android进阶(二十六)MenuInflater实现菜单添加
- Android进阶(二十六)MenuInflater实现菜单添加
- @dynamic的使用
- 字符编码笔记:ASCII,Unicode和UTF-8
- QUdpSocket的问题
- Linux下ffmpeg视频转码的几个例子
- NoSQL总结分类
- Android高手进阶教程(二十六)之---Android超仿Path菜单的实现!
- ffmpeg参数
- 怎么样才能稳定使用google 搜索?
- hdu4446 IT Companies
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- Linux C/C++ GDB教程详解
- Android高手进阶教程(二十八)之---Android ViewPager控件的使用(基于ViewPager的横向相册)!!!
- NoSQL 数据建模技术
- linux 端tomcat监控程序(JAVA版)