超酷的计步器APP(一)——炫酷功能实现,自定义水波纹特效、自定义炫酷开始按钮、属性动画的综合体验

好久没写博客了,没给大家分享技术了,真是有些惭愧。这段时间我在找工作,今年Android的行情也不怎么好,再加上我又是一个应届生,所以呢,更是不好找了。但是我没有放弃,经过自己的不懈努力,还是找到了自己喜欢的Android工作,心里的一块石头终于落下了。但是迎接我来的是更多的挑战,我喜欢那种不断的挑战自我,在困难中让自己变得更强大的感觉。相信阳光总在风雨后,因为每一个你不满意的现在,都有一个你没有努力的曾经。所以我们一起努力,为了生活,生下来、活下去。


今天我们来一起学习一个很酷的小项目——计步器。
关于这个项目我想分两篇博客来和大家分享,一篇先来学习界面和功能中用到的自定义控件,下篇来实现动画和计步器连接起来开始计算步数的效果
我们先来看效果图。

是不是很酷很炫呢,哈哈,我觉得酷酷哒。
那么我们今天先来学习那个很酷的效果图的实现。
点击开始按钮,出现结束和暂停按钮,开始按钮隐藏,横线变波浪的效果

我们先新建一个Android项目,开始在main_activity.xml中书写布局
先来看这个布局的Component Tree

我们来写他的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/bg4_dark_blackish_green"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/activity_walking_backgroud"android:orientation="vertical"><include layout="@layout/top_bar" /><TextViewandroid:id="@+id/step_count"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="90dp"android:textColor="@color/white"android:textSize="70sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_marginTop="18dp"android:text="计算步数"android:textColor="@color/white"android:textSize="13sp" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="35dp"android:layout_marginLeft="30dp"android:layout_marginRight="50dp"android:layout_marginTop="60dp"android:orientation="horizontal"android:weightSum="2"><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"><ImageViewandroid:id="@+id/iv_calories"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:src="@mipmap/calories" /><TextViewandroid:id="@+id/calories"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_toRightOf="@id/iv_calories"android:textColor="@color/white"android:textSize="24sp" /><TextViewandroid:id="@+id/tv_calories"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/calories"android:layout_toRightOf="@id/iv_calories"android:text="热量:千卡"android:textColor="@color/white"android:textSize="10sp" /></RelativeLayout><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"><ImageViewandroid:id="@+id/iv_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:src="@mipmap/time" /><TextViewandroid:id="@+id/time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_toRightOf="@id/iv_time"android:text="0"android:textColor="@color/white"android:textSize="24sp" /><TextViewandroid:id="@+id/tv_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/time"android:layout_toRightOf="@id/iv_time"android:text="时间:分钟"android:textColor="@color/white"android:textSize="10sp" /></RelativeLayout></LinearLayout></LinearLayout><com.adu.running.view.WaveViewandroid:id="@+id/wave_view"android:layout_width="match_parent"android:layout_height="40dp"android:layout_marginTop="-20dp"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:layout_marginTop="27dp"><com.adu.running.view.CircleButtonandroid:id="@+id/stop"android:layout_width="94dp"android:layout_height="94dp"android:layout_alignParentLeft="true"android:layout_centerVertical="true"android:layout_gravity="center"android:text="结束"android:textColor="@color/white"android:visibility="gone"/><com.adu.running.view.CircleWaveButtonandroid:id="@+id/start"android:layout_width="94dp"android:layout_height="94dp"android:layout_centerInParent="true"android:textColor="@color/white"/><com.adu.running.view.CircleButtonandroid:id="@+id/bt_continue"android:layout_width="94dp"android:layout_height="94dp"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_gravity="center"android:text="暂停"android:textColor="@color/white"android:visibility="gone"/></RelativeLayout></LinearLayout>

如果你直接复制上面的代码到你的项目中肯定会报错的,因为上面的布局中我们引用了一个自定义的toolbar布局和几个颜色值,还有几个自定义View
一会我会把代码给大家传上去,或者直接看我GitHub上面的源码

我们现在看下面的三个自定义View怎么来完成的

WaveView.java自定义波纹类

package com.adu.running.view;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;/*** Created by adu on 2016/10/30.*/public class WaveView extends View {//波纹颜色private int waveColor = 0xff0099CC;// 振幅private float swing = 0;private int height;private int width;private int ms = 30;private float isPause=0f;private boolean isRun = false;//绘制波纹的画笔private Paint wavePaint;//Path类可以预先在View上将N个点连成一条"路径"// 然后调用Canvas的drawPath(path,paint)即可沿着路径绘制图形private Path path1;private Path path2;private Path path3;public WaveView(Context context) {super(context);init();}public WaveView(Context context, AttributeSet attrs) {super(context, attrs);init();}public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {// 初始绘制波纹的画笔wavePaint = new Paint();// 去除画笔锯齿wavePaint.setAntiAlias(true);//设置画笔颜色wavePaint.setColor(waveColor);//设置线宽wavePaint.setStrokeWidth(5);//设置风格为空心wavePaint.setStyle(Paint.Style.STROKE);path1 = new Path();path2 = new Path();path3 = new Path();}/*** 计算view高度宽度大小* @param widthMeasureSpec* @param heightMeasureSpec*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);initLayoutParams();}private void initLayoutParams() {height = this.getHeight();width = this.getWidth();}@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);setPath();wavePaint.setStrokeWidth(6);wavePaint.setAlpha(100);//设置透明度canvas.drawPath(path1, wavePaint);wavePaint.setStrokeWidth(3);wavePaint.setAlpha(80);canvas.drawPath(path2, wavePaint);wavePaint.setAlpha(60);canvas.drawPath(path3, wavePaint);}/*** 设置三个线条上下震动的振幅*/private void setPath() {int x = 0;int y = 0;path1.reset();//清除掉path里的线条和曲线for (int i = 0; i < width; i++) {x = i;y = (int) (isPause*40* Math.sin(i * 2*0.7f * Math.PI / width+swing) + height*0.5);if (i == 0) {path1.moveTo(x, y);//定位绘画开始位置}//绘制圆滑曲线,即贝塞尔曲线;(x, y)为控制点,(x + 1, y)为结束点path1.quadTo(x, y, x + 1, y);}path2.reset();for (int i = 0; i < width; i++) {x = i;y = (int) (isPause*40* Math.sin(i * 2*0.7f * Math.PI / width+swing+0.3f) + height*0.5);if (i == 0) {path2.moveTo(x, y);}path2.quadTo(x, y, x + 1, y);}path3.reset();for (int i = 0; i < width; i++) {x = i;y = (int) (isPause*40* Math.sin(i * 2*0.7f * Math.PI / width+swing+0.3f) + height*0.5);if (i == 0) {path3.moveTo(x, y);}path3.quadTo(x, y, x + 1, y);}path1.close();//回到初始点形成封闭的曲线path2.close();path3.close();}public void start(){this.isRun=true;this.isPause=1.0f;new MyThread().start();//让波纹在子线程中运行}public void stop(){this.isRun=false;this.isPause=0.0f;invalidate();//请求重新绘制的界面}private class MyThread extends Thread {@Overridepublic void run() {while (isRun) {swing+=-0.25f;mHandler.sendEmptyMessage(1);try {Thread.sleep(ms);} catch (InterruptedException e) {e.printStackTrace();}}}}private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {if (msg.what == 1) {invalidate();//请求重新绘制的界面}}};
}

让我们在MainActivity的布局中新建两个Button按钮开对自定义波纹类进行测试,分别调用它的start( )和stop( )方法,运行结果如下:

点击开始,波纹会上下起伏,点击停止,它会恢复到停止状态
接着,我们看下面的三个按钮是怎么实现的,其实是两个自定义的Button

CircleWaveButton.java 开始按钮

package com.adu.running.view;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.widget.Button;
import com.adu.running.R;/*** Created by adu on 2016/10/30.*/public class CircleWaveButton extends Button{//这是默认颜色private int paintColor= R.color.circle_bule_bbd4e7;//画圆的画笔private Paint paint = new Paint();//画字的画笔private Paint textPaint = new Paint();private int radiusInt = 0;//这是默认文字内容private String text="开始";private Boolean isStart = false;private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);invalidate();if (isStart) {radiusInt++;if (radiusInt > 50) {radiusInt = 0;}sendEmptyMessageDelayed(0, 20);}}};public CircleWaveButton(Context context) {super(context);init();}public CircleWaveButton(Context context, AttributeSet attrs) {super(context, attrs);init();}public CircleWaveButton(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {setBackgroundColor(getResources().getColor(R.color.running));}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);int centre = getWidth() / 2;int radius = centre;//绘制圆的画笔Paint newPaint = new Paint();newPaint.setAntiAlias(true);        // 去除画笔锯齿newPaint.setStyle(Paint.Style.FILL);// 设置风格为实线//用来进行环形渲染Shader shader = new RadialGradient(centre, centre, radius, getResources().getColor(paintColor), getResources().getColor(R.color.running), Shader.TileMode.CLAMP);//设置图像效果,使用Shader可以绘制出各种渐变效果newPaint.setShader(shader);//绘制圆形(圆心的x坐标,圆心的y坐标,圆的半径,绘制时所使用的画笔)canvas.drawCircle(centre, centre, radius, newPaint);paint.setColor(getResources().getColor(paintColor));paint.setStyle(Paint.Style.FILL);   //设置风格为实线paint.setAntiAlias(true);           // 去除画笔锯齿for(int i=1;i<=5;i++){paint.setAlpha(20*i);//设置绘制图形的透明度//绘制圆形(圆心的x坐标,圆心的y坐标,圆的半径,绘制时所使用的画笔)canvas.drawCircle(centre, centre, radius * (10- i)/ 10, paint);}paint.setColor(getResources().getColor(paintColor));paint.setStyle(Paint.Style.STROKE);     //设置风格为空心paint.setStrokeWidth(radius * 2 / 12);  //设置线宽for(int i=0;i<3;i++) {paint.setAlpha(60-i*20);//设置绘制图形的透明度//绘制圆形(圆心的x坐标,圆心的y坐标,圆的半径,绘制时所使用的画笔)canvas.drawCircle(centre, centre, radius * (14-i*2 + radiusInt / 50.0f) / 16, paint);}textPaint.setTextSize(getTextSize());textPaint.setAntiAlias(true);textPaint.setStyle(Paint.Style.FILL);textPaint.setColor(getTextColors().getDefaultColor());//获取文字的宽度值float length = textPaint.measureText(text);//绘制文字canvas.drawText(text, centre - length / 2, centre + getTextSize() / 3, textPaint);}public void start() {isStart = true;handler.sendEmptyMessage(0);}public void stop() {isStart = false;handler.removeMessages(0);}
}

我们在MainActivity设置CircleWaveButton的点击事件调用它的start( )方法,会看到下面的效果

下面我们看最后一个自定义Button,结束的Button和暂停的Button只是颜色不一样,其他都是一样的。

CircleButton.xml暂停结束按钮

package com.adu.running.view;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.Button;
import com.adu.running.R;/*** Created by adu on 2016/10/30.*/public class CircleButton extends Button {//画圆private Paint paint = new Paint();//画字private Paint textPaint = new Paint();private int color;public CircleButton(Context context) {super(context);init();}public CircleButton(Context context, AttributeSet attrs) {super(context, attrs);init();}public CircleButton(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {setBackgroundColor(getResources().getColor(R.color.running));color=getResources().getColor(R.color.running);}@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);int centre = getWidth() / 2;int radius = centre;paint.setColor(color);paint.setStyle(Paint.Style.FILL);paint.setAntiAlias(true);//绘制圆形(圆心的x坐标,圆心的y坐标,圆的半径,绘制时所使用的画笔)canvas.drawCircle(centre, centre, radius, paint);textPaint.setTextSize(getTextSize());textPaint.setAntiAlias(true);textPaint.setStyle(Paint.Style.FILL);textPaint.setColor(getTextColors().getDefaultColor());float length = textPaint.measureText(getText().toString());//绘制文字canvas.drawText(getText().toString(), centre - length / 2, centre + getTextSize() / 3, textPaint);}//改变文字颜色public void setPaintColor(int color) {this.color = getResources().getColor(color);}
}

我们就不在测试这个Button了,直接写开始的那个效果
点击开始按钮,然后隐藏它,一个动画的效果出现结束和暂停按钮,并且开启波纹,点暂停波纹停止,点击结束退出。
我们之间在MainActivity中写代码

package com.adu.running;import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Point;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.adu.running.view.CircleButton;
import com.adu.running.view.CircleWaveButton;
import com.adu.running.view.WaveView;public class MainActivity extends AppCompatActivity {@BindView(R.id.wave_view) WaveView waveView;@BindView(R.id.startButton) CircleWaveButton startButton;   //开始@BindView(R.id.stop) CircleButton stopButton;               //停止@BindView(R.id.bt_continue) CircleButton btContinue;        //暂停继续private boolean isPause = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);initView();}private void initView() {btContinue.setPaintColor(R.color.text_color_1e78be);startButton.setPaintColor(R.color.circle_bule_bbd4e7);stopButton.setPaintColor(R.color.circle_red_cd3a33);startButton.start();}@OnClick({ R.id.stop, R.id.startButton, R.id.bt_continue })public void onClick(View view) {switch (view.getId()) {case R.id.stop:     //停止并退出System.exit(0);break;case R.id.startButton:  //开始startAnimation();waveView.start();break;case R.id.bt_continue:  //暂停继续if (isPause){btContinue.setText("暂停");isPause = false;waveView.start();}else {btContinue.setText("继续");isPause = true;waveView.stop();}break;}}/*** 按钮动画效果实现的方法*/private void startAnimation() {btContinue.setVisibility(View.VISIBLE);//显示暂停按钮stopButton.setVisibility(View.VISIBLE);//显示停止按钮//获取屏幕的大小,并把屏幕的宽也就是x赋值给widthWindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);Display display = wm.getDefaultDisplay();Point size = new Point();display.getSize(size);int width = size.x;//属性动画,传入"alpha"参数,将开始按钮从不透明改变为透明Animator animatorStart = ObjectAnimator.ofFloat(startButton, "alpha", 1.0f, 0f);AnimatorSet animatorSetStart = new AnimatorSet();//组合动画animatorSetStart.playTogether(animatorStart);animatorSetStart.setInterpolator(new DecelerateInterpolator());//动画效果设置为减速animatorSetStart.setDuration(1000);//设置动画时长//将暂停按钮由透明改变为不透明Animator animatorContinue1 = ObjectAnimator.ofFloat(btContinue, "alpha", 0f, 1.0f);animatorContinue1.setDuration(3000);//设置动画时长//将暂停按钮从中间向右边移动Animator animatorContinue2 = ObjectAnimator.ofFloat(btContinue, "translationX", -width / 3, btContinue.getX());animatorContinue2.setDuration(2000);//设置动画时长AnimatorSet animatorSetContinue = new AnimatorSet();animatorSetContinue.playTogether(animatorContinue1, animatorContinue2);// 并行animatorSetContinue.setInterpolator(new DecelerateInterpolator());//动画效果设置为减速//将结束按钮由透明改变为不透明Animator animatorStop1 = ObjectAnimator.ofFloat(stopButton, "alpha", 0f, 1.0f);animatorStop1.setDuration(3000);//设置动画时长//将结束按钮从中间向左边移动Animator animatorStop2 = ObjectAnimator.ofFloat(stopButton, "translationX", width / 3, 0);animatorStop2.setDuration(2000);//设置动画时长AnimatorSet animatorSetStop = new AnimatorSet();animatorSetStop.playTogether(animatorStop1, animatorStop2);// 并行animatorSetStop.setInterpolator(new DecelerateInterpolator());//动画效果设置为减速//启动三个按钮动画animatorSetStart.start();animatorSetStop.start();animatorSetContinue.start();startButton.setVisibility(View.GONE);}
}

我们运行代码,看看效果

我们就简单的完成了一个这样的动画效果,看起来还是蛮酷的嘛。


这篇博客,我们主要学习了三个自定义View的实现,然后组合在一起形成一个很酷的效果。
下篇博客,我开始给大家讲这个动画和计步器连接起来开始计算步数的效果

我把这篇博客的Demo上传到这里,如果想直接看完整的动画和计步器的代码,请大家看我的GitHub,如果喜欢的话可以star一下,谢谢大家的支持


欢迎有兴趣的同学加我朋友的QQ群:点击直接加群555974449 我们一起来玩吧。

点击下载Demo

超酷的计步器APP(一)——炫酷功能实现,自定义水波纹特效、自定义炫酷开始按钮、属性动画的综合体验相关推荐

  1. Qt系列——炫酷的Qt APP+STM32平衡小车

    一. Qt设计 采用了C++--Qt设计了炫酷的主页面,里面包含了各类仪表widget,其中有个类似钢铁侠的按钮可以触发和控制平衡小车的蜂鸣器.设计的摇杆按钮可以控制前进.后退.左转.右转.蓝牙连接等 ...

  2. 基于HTML5实现的超酷摄像头(HTML5 webcam)拍照功能 - photobooth.js

    在线演示  下载 WebRTC可能是明年最受关注的HTML5标准了,Mozilla为此开发了一套帮助你控制硬件的API,例如,摄像头,麦克风,或者是加速表.你可以不依赖其它的插件来调用你需要的本机硬件 ...

  3. css3特效框,科技常识:6种非常炫酷的CSS3按钮边框动画特效

    今天小编跟大家讲解下有关6种非常炫酷的CSS3按钮边框动画特效 ,相信小伙伴们对这个话题应该有所关注吧,小编也收集到了有关6种非常炫酷的CSS3按钮边框动画特效 的相关资料,希望小伙伴们看了有所帮助. ...

  4. 超级炫酷夜场酒吧KTV宣传视频模板 镂空文字故障闪屏特效PR模板

    超级炫酷夜场酒吧KTV宣传视频模板 镂空文字故障闪屏特效PR模板 超级时尚炫酷Premiere夜场酒吧KTV宣传视频模板,具有动态场景,频闪效果和原始过渡.该模板具有9个媒体占位符,8个可编辑文本层和 ...

  5. 年会活动html酷炫抽奖功能-高端版

    年会活动html酷炫抽奖功能-高端版 界面效果展示 资源下载地 (https://download.csdn.net/download/weixin_43151418/85508943)

  6. 数据如何指导决策:优酷主客APP播转率的C端优化

    一.背景介绍 1. 了解「播转率」及相关业务 优酷是一个综合视频平台,用户到访优酷是为了观看视频.对于平台来说,希望到访的用户都能找到自己想看的内容,收获满意的用户体验,达成后续的留存与持续活跃. & ...

  7. html边框炫酷效果,6种炫酷的CSS3按钮边框动画特效_html/css_WEB-ITnose

    这是一款效果非常炫酷的CSS3按钮边框动画特效.这组按钮边框动画共有6种不同的效果.当鼠标滑过按钮的时候,按钮的边框会以不同的方式进行各种动画,效果非常的炫酷. 在线预览 源码下载 使用方法 HTML ...

  8. android仿疯狂猜图源码,Android开发实现高仿优酷的客户端图片左右滑动切换功能实例【附源码下载】...

    本文实例讲述了Android开发实现高仿优酷的客户端图片左右滑动切换功能.分享给大家供大家参考,具体如下: 本例是用ViewPager去做的实现,支持自动滑动和手动滑动,不仅优酷网,实际上有很多商城和 ...

  9. android的优酷菜单,Android利用属性动画实现优酷菜单

    利用属性动画实现优酷菜单,供大家参考,具体内容如下 布局文件 xmlns:tools="http://schemas.android.com/tools" android:layo ...

最新文章

  1. tfjob的一篇文章,跟公司内使用方式类似
  2. 网站无法显示logo?
  3. TCP/IP 广播的发送和接收
  4. overlay网络的优势
  5. Interesting Finds: 2008.03.17
  6. java8之重新认识HashMap(转自美团技术团队)
  7. 有什么产品工作,可以每天摸胸,还不用冒生命危险?
  8. Python 学习笔记 多进程 multiprocessing
  9. Axure 共享强制签出签入
  10. MYSQL的replace into
  11. 反直觉的三门问题,为什么80%的人都错了?
  12. background背景图片自适应_一侧定宽、一侧自适应,尽量多的方案实现?「前端剑指offer」...
  13. [Unity] Unity3D研究院编辑器之自定义默认资源的Inspector面板
  14. 网页编辑器粘贴word格式的处理
  15. 《Java核心技术 卷1 基础知识 原书第10版》
  16. 线性规划图解法求最优解_线性规划的图解法6.ppt
  17. android stub,Android:ViewStub
  18. 调用网站第三方接口实现短信发邮件
  19. matlab fzsxl函数,复指数函数或序列的绘制
  20. jquery.qrcode.js生成二维码

热门文章

  1. 近期Google发布了关于Google Play应用商店的重要调整
  2. 前端如何修改组件库源码来封装符合自己需求的组件?
  3. 刘帅嵌入式系统-BLX(2)
  4. 关于金蝶云星空安装问题
  5. centos安装erlang
  6. 骨感传导蓝牙耳机怎么样,骨感传导耳机对于我们耳道是否有保护
  7. 小米6X Android耗电,小米6x电池耐用吗 小米6X充电测试
  8. MacBook入门之——开机激活教程
  9. 软考项目管理(案例分析)
  10. 非IT专业应届毕业生的第一次面试,某乙方公司,JAVA开发岗位,问题很简单,在这里总结下。