转载请标明出处:
http://blog.csdn.net/hai_qing_xu_kong/article/details/50789666
本文出自:【顾林海的博客】

####扯蛋篇
这几由于智齿又长了出来,痛了好几天还没好,吃饭又不能吃,加上公司里面操蛋的体制,感觉人活着真累,昨天晚上回到住处,我朋友让我帮忙写个唱片播放器,效果大致上如下:

于是乎,利用一个早上做了下,比较粗糙,毕竟帮别人做的,随便做做得了,当然有很多地方投机取巧了。

####原理篇

在做之前看看我们得需要以下素材:

额!!!这个,这个ic_launcher忽律。

现在我们分析这个播放器的几个播放步骤:

  1. 当我们杆放到碟子上时,碟子需要旋转
  2. 在碟子旋转时,向上或是向下滑动淡出(PS:这里面我为了方便,放了两层的碟子View,这样上面滑出时,底下的唱片还是显示的)
  3. 当我们拨动杆时,杆逐渐移动到唱片上,再次触摸杆时,杆回到原来的位置(PS:这里有个问题,就是杆移动到唱片上时,触摸事件其实还是在原来的位置,这里我们在唱片右下角放了一个透明的View,嘿嘿,投机取巧嘛,也是说,我在原来的位置只处理向右移动的操作,这个透明的View只处理杆归位的操作)

讲了这么多,先看看布局吧

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center" ><FrameLayoutandroid:layout_width="260dp"android:layout_height="match_parent"android:layout_centerInParent="true" ><FrameLayoutandroid:id="@+id/fl_dvd"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="center" ><FrameLayoutandroid:id="@+id/fl_dvd1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center" ><ImageViewandroid:id="@+id/iv_background1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:src="@drawable/turntable_bg_anim_highlight" /><ImageViewandroid:id="@+id/iv_center1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:src="@drawable/default_album" /></FrameLayout><FrameLayoutandroid:id="@+id/fl_dvd2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center" ><ImageViewandroid:id="@+id/iv_background2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:src="@drawable/turntable_bg_anim_highlight" /><ImageViewandroid:id="@+id/iv_center2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:src="@drawable/default_album" /></FrameLayout></FrameLayout><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:src="@drawable/turntable_bg" /><ImageViewandroid:id="@+id/iv_pole"android:layout_width="50sp"android:layout_height="180sp"android:layout_gravity="right|center"android:src="@drawable/stylus" /><Viewandroid:id="@+id/id_pole"android:layout_width="40dp"android:layout_height="40dp"android:layout_gravity="center"android:layout_marginLeft="65dp"android:layout_marginTop="45dp" /></FrameLayout><FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent" ></FrameLayout></RelativeLayout>

这里的id为 fl_dvd1 的FrameLayout是底部的唱片View, id为 fl_dvd2的FrameLayout是上面用来做移出动画的唱片View,id为 id_pole的View就是唱片右下角透明的View,旋转的是id 为 fl_dvd的View。

首先定义一个继承LinearLayout的BaseRecordView类:

public abstract class BaseRecordView extends LinearLayout {}

接着重写三个构造器:

public BaseRecordView(Context context) {this(context, null);
}public BaseRecordView(Context context, AttributeSet attrs) {this(context, attrs, 0);
}public BaseRecordView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);this.mContext = context;init();initAnimation();initEvent();
}

init方法里是载入我们刚定义的布局,并初始化控件:

/*** 初始化View* * @param context*/private void init() {mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();LayoutInflater.from(mContext).inflate(R.layout.record_layout, this);fl_dvd = (FrameLayout) findViewById(R.id.fl_dvd);// 两层 碟片的容器fl_dvd2 = (FrameLayout) findViewById(R.id.fl_dvd2);// 移出唱片动画的Viewiv_background2 = (ImageView) findViewById(R.id.iv_background2);// 黑色的唱片(移出唱片动画的View)iv_center2 = (ImageView) findViewById(R.id.iv_center2);// 中间的圆心图案(移出唱片动画的View)iv_pole = (ImageView) findViewById(R.id.iv_pole);// 杆mPole = findViewById(R.id.id_pole);// 唱片右下角透明的View}

mTouchSlop 拿到的是当面屏幕滑动的最小距离。

第一步先让整个唱片旋转,也就是 **fl_dvd **这个View进行旋转,可以通过Animation进行播放动画,先配置我们的动画文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" ><rotateandroid:duration="2400"android:fillAfter="true"android:fillBefore="false"android:fromDegrees="0"android:pivotX="50%"android:pivotY="50%"android:repeatCount="-1"android:toDegrees="359" /></set>

通过设置repeatCount属性为-1,使唱片无限旋转。定义唱片旋转的动画。

/**
* 碟片的播放动画
*/
private void initDVDAnimation() {mDVDLin = new LinearInterpolator();mDVDAnimtion = AnimationUtils.loadAnimation(mContext, R.anim.dvd_anim);mDVDAnimtion.setInterpolator(mDVDLin);mDVDAnimtion.setFillAfter(true);mDVDAnimtion.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}});
}

杆的拨动到唱片上的效果,是将我们的图片顺时针旋转20度,那么杆的复位是逆时针旋转20度,定义我们的杆拨打的动画文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" ><rotateandroid:duration="300"android:fromDegrees="0"android:pivotX="45%"android:pivotY="10%"android:repeatCount="0"android:toDegrees="20" /></set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" ><rotateandroid:duration="300"android:fromDegrees="0"android:pivotX="45%"android:pivotY="10%"android:repeatCount="0"android:toDegrees="20" /></set>

老样子初始化我们杆的动画:

/**
* 杆子启动动画
*/
private void initPoleAnimation() {mPoleAnimtion = AnimationUtils.loadAnimation(mContext, R.anim.pole_anim);mPoleLin = new LinearInterpolator();mPoleAnimtion.setFillAfter(true);mPoleAnimtion.setInterpolator(mPoleLin);mPoleAnimtion.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {/** 杆子启动完毕,说明碟子应该要转动了*/isStart = true;isPole = true;startDVDAnimation();mIRecordListener.start();}@Overridepublic void onAnimationRepeat(Animation animation) {}});}/**
* 杆复位动画
*/
private void initPoleStopAnimation() {mPoleAnimtion = AnimationUtils.loadAnimation(mContext,R.anim.pole_rest_anim);mPoleLin = new LinearInterpolator();mPoleAnimtion.setFillAfter(true);mPoleAnimtion.setInterpolator(mPoleLin);mPoleAnimtion.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {/** 杆子复位,说明已经停止播放或者播放完毕*/isPole = false;isStart = false;stopDVDAnimation();mIRecordListener.stop();}@Overridepublic void onAnimationRepeat(Animation animation) {}});}

上面在杆放到唱片上后,调用startDVDAnimation方法进行唱片的旋转,并通过接口回调通知我们的当前处于播放状态;当杆复位时调用stopDVDAnimation方法进行唱片的停止,并通过接口回调通知我们的当前处于停止状态。

接着添加我们杆的触摸事件,注意还有我们投机取巧的透明View的触摸事件:

/**
* 杆触摸事件
*/
iv_pole.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_MOVE:break;case MotionEvent.ACTION_UP:if (!isStart) {/** 当停止播放时,拨动杆,播放*/isPole = true;startPoleAnimation();}break;default:break;}return true;}
});/**
* 虚拟位置的触摸
*/
mPole.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_MOVE:break;case MotionEvent.ACTION_UP:if (isStart) {/** 当播放时,拨动杆,停止*/isPole = false;stopPoleAnimation();}break;default:break;}return true;}
});

通过触摸杆和透明的View来决定是否进行杆的复位还是移动到唱片上。

最后是唱片本身触摸的事件处理:

/**
* 碟片的触摸事件
*/
private OnTouchListener mOnTouchListener = new OnTouchListener() {@Override
public boolean onTouch(View v, MotionEvent event) {int oldY = (int) event.getX();int newY = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:oldY = (int) event.getY();break;case MotionEvent.ACTION_MOVE:newY = (int) event.getY();stopDVDAnimation();break;case MotionEvent.ACTION_UP:if (isStart && oldY - newY > mTouchSlop && (newY < oldY)) {up();} else if (isStart && newY - oldY > mTouchSlop && (newY > oldY)) {down();} else if (isPole) {startDVDAnimation();}break;default:break;}return true;
}};

这里面是滑动时的唱片停止处理,以及向上向下滑动时的处理,小于滑动最小距离并离开屏幕时,唱片重新旋转。

最后给出up和down的方法:

/**
* 碟片向上切歌动画
*/
private void initDVDUpAnimation() {mUpAnimation = AnimationUtils.loadAnimation(mContext, R.anim.up_anim);mUpAnimation.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {mIRecordListener.up();}@Overridepublic void onAnimationEnd(Animation animation) {fl_dvd2.setVisibility(View.VISIBLE);startDVDAnimation();}@Overridepublic void onAnimationRepeat(Animation animation) {}});
}/**
* 碟片向下切歌动画
*/
private void initDVDDownAnimation() {mDownAnimation = AnimationUtils.loadAnimation(mContext,R.anim.down_anim);mDownAnimation.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {mIRecordListener.down();}@Overridepublic void onAnimationEnd(Animation animation) {fl_dvd2.setVisibility(View.VISIBLE);startDVDAnimation();}@Overridepublic void onAnimationRepeat(Animation animation) {}});}

完整的代码:

package com.example.recordproject.widget;import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;import com.example.recordproject.R;
import com.example.recordproject.widget.interf.IRecordListener;/*** 唱片* * @author Linhai Gu* */
public abstract class BaseRecordView extends LinearLayout {/*** 上下文*/protected Context mContext;/*** 碟片*/private FrameLayout fl_dvd;/*** 碟片上面*/private FrameLayout fl_dvd2;/*** 碟片动画*/private Animation mDVDAnimtion;/*** 碟片播放动画的速度匀速*/private LinearInterpolator mDVDLin;/*** 杆*/private ImageView iv_pole;/*** 杆动画*/private Animation mPoleAnimtion;/*** 杆播放动画的速度匀速*/private LinearInterpolator mPoleLin;/*** 向上切歌*/private Animation mUpAnimation;/*** 向下切歌*/private Animation mDownAnimation;/*** 滑动的最小距离*/private int mTouchSlop;/*** 浮层碟片*/private ImageView iv_center2;private ImageView iv_background2;private View mPole;/*** 是否正在播放*/private boolean isStart = false;/*** 杆是否在碟片上*/private boolean isPole = false;private IRecordListener mIRecordListener;protected abstract void setRecordListener(IRecordListener listener);protected abstract void start();protected abstract void stop();public BaseRecordView(Context context) {this(context, null);}public BaseRecordView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public BaseRecordView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);this.mContext = context;init();initAnimation();initEvent();}/*** 初始化View* * @param context*/private void init() {mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();LayoutInflater.from(mContext).inflate(R.layout.record_layout, this);fl_dvd = (FrameLayout) findViewById(R.id.fl_dvd);// 两层 碟片的容器fl_dvd2 = (FrameLayout) findViewById(R.id.fl_dvd2);// 移出唱片动画的Viewiv_background2 = (ImageView) findViewById(R.id.iv_background2);// 黑色的唱片(移出唱片动画的View)iv_center2 = (ImageView) findViewById(R.id.iv_center2);// 中间的圆心图案(移出唱片动画的View)iv_pole = (ImageView) findViewById(R.id.iv_pole);// 杆mPole = findViewById(R.id.id_pole);// 唱片右下角透明的View}/*** <pre>* {@link #initDVDAnimation}初始化碟片动画* {@link #initDVDUpAnimation}初始向上切歌的动画*  {@link #initDVDDownAnimation}初始向下切歌的动画* </pre>*/private void initAnimation() {initDVDAnimation();initDVDUpAnimation();initDVDDownAnimation();}/*** 碟片的触摸事件*/private OnTouchListener mOnTouchListener = new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {int oldY = (int) event.getX();int newY = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:oldY = (int) event.getY();break;case MotionEvent.ACTION_MOVE:newY = (int) event.getY();stopDVDAnimation();break;case MotionEvent.ACTION_UP:if (isStart && oldY - newY > mTouchSlop && (newY < oldY)) {up();} else if (isStart && newY - oldY > mTouchSlop && (newY > oldY)) {down();} else if (isPole) {startDVDAnimation();}break;default:break;}return true;}};/*** 初始化事件*/private void initEvent() {/*** 碟片的触摸事件*/iv_background2.setOnTouchListener(mOnTouchListener);iv_center2.setOnTouchListener(mOnTouchListener);/*** 杆触摸事件*/iv_pole.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_MOVE:break;case MotionEvent.ACTION_UP:if (!isStart) {/** 当停止播放时,拨动杆,播放*/isPole = true;startPoleAnimation();}break;default:break;}return true;}});/*** 虚拟位置的触摸*/mPole.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_MOVE:break;case MotionEvent.ACTION_UP:if (isStart) {/** 当播放时,拨动杆,停止*/isPole = false;stopPoleAnimation();}break;default:break;}return true;}});}/*** 碟片的播放动画*/private void initDVDAnimation() {mDVDLin = new LinearInterpolator();mDVDAnimtion = AnimationUtils.loadAnimation(mContext, R.anim.dvd_anim);mDVDAnimtion.setInterpolator(mDVDLin);mDVDAnimtion.setFillAfter(true);mDVDAnimtion.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}});}/*** 碟片向上切歌动画*/private void initDVDUpAnimation() {mUpAnimation = AnimationUtils.loadAnimation(mContext, R.anim.up_anim);mUpAnimation.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {mIRecordListener.up();}@Overridepublic void onAnimationEnd(Animation animation) {fl_dvd2.setVisibility(View.VISIBLE);startDVDAnimation();}@Overridepublic void onAnimationRepeat(Animation animation) {}});}/*** 碟片向下切歌动画*/private void initDVDDownAnimation() {mDownAnimation = AnimationUtils.loadAnimation(mContext,R.anim.down_anim);mDownAnimation.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {mIRecordListener.down();}@Overridepublic void onAnimationEnd(Animation animation) {fl_dvd2.setVisibility(View.VISIBLE);startDVDAnimation();}@Overridepublic void onAnimationRepeat(Animation animation) {}});}/*** 杆子启动动画*/private void initPoleAnimation() {mPoleAnimtion = AnimationUtils.loadAnimation(mContext, R.anim.pole_anim);mPoleLin = new LinearInterpolator();mPoleAnimtion.setFillAfter(true);mPoleAnimtion.setInterpolator(mPoleLin);mPoleAnimtion.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {/** 杆子启动完毕,说明碟子应该要转动了*/isStart = true;isPole = true;startDVDAnimation();mIRecordListener.start();}@Overridepublic void onAnimationRepeat(Animation animation) {}});}/*** 杆复位动画*/private void initPoleStopAnimation() {mPoleAnimtion = AnimationUtils.loadAnimation(mContext,R.anim.pole_rest_anim);mPoleLin = new LinearInterpolator();mPoleAnimtion.setFillAfter(true);mPoleAnimtion.setInterpolator(mPoleLin);mPoleAnimtion.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {/** 杆子复位,说明已经停止播放或者播放完毕*/isPole = false;isStart = false;stopDVDAnimation();mIRecordListener.stop();}@Overridepublic void onAnimationRepeat(Animation animation) {}});}/*** 播放碟片动画*/private void startDVDAnimation() {fl_dvd.startAnimation(mDVDAnimtion);}/*** 暂停碟片动画*/private void stopDVDAnimation() {fl_dvd.clearAnimation();// mDVDAnimtion.cancel();}/*** 播放杆的动画*/protected void startPoleAnimation() {initPoleAnimation();// mPoleAnimtion.cancel();iv_pole.startAnimation(mPoleAnimtion);}/*** 暂停杆的动画*/protected void stopPoleAnimation() {// iv_pole.clearAnimation();initPoleStopAnimation();if (mPoleAnimtion != null) {mPoleAnimtion.cancel();}iv_pole.startAnimation(mPoleAnimtion);}/*** 向上切歌*/private void up() {fl_dvd2.startAnimation(mUpAnimation);}/*** 向下切歌*/private void down() {fl_dvd2.startAnimation(mDownAnimation);}/*** 监听* * @param listener*/protected void initListener(IRecordListener listener) {this.mIRecordListener = listener;}
}
package com.example.recordproject.widget;import com.example.recordproject.widget.interf.IRecordListener;import android.content.Context;
import android.util.AttributeSet;public class RecordView extends BaseRecordView {public RecordView(Context context) {this(context, null);}public RecordView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RecordView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}@Overridepublic void setRecordListener(IRecordListener listener) {super.initListener(listener);}@Overridepublic void start() {startPoleAnimation();}@Overridepublic void stop() {stopPoleAnimation();}}
package com.example.recordproject.widget.interf;public interface IRecordListener {/*** 开始*/public void start();/*** 关闭*/public void stop();/*** 向上切歌*/public void up();/*** 向下切歌*/public void down();}
package com.example.recordproject;import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;import com.example.recordproject.widget.RecordView;
import com.example.recordproject.widget.interf.IRecordListener;public class MainActivity extends Activity {private RecordView mRecordView;private int count = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initViews();}private void initViews() {mRecordView = (RecordView) findViewById(R.id.mRecordView);mRecordView.setRecordListener(new IRecordListener() {@Overridepublic void stop() {Log.e("TAG", "-----停止-----");}@Overridepublic void start() {Log.e("TAG", "-----开启-----");}@Overridepublic void up() {Log.e("TAG", "-----向上切歌-----");}@Overridepublic void down() {Log.e("TAG", "-----向下切歌-----");}});}
}

以下是项目的完整github地址。

github项目源码地址:点击【项目源码】

Android之一起制作简易唱片播放器相关推荐

  1. 基于Android系统开发的简易音乐播放器

    大概做了一周左右,一个简易版本的音乐播放器.主要有三个界面,先上图: 一个主界面:主要负责1加载外部存储的音乐文件信息到应用内置数据库中2转到音乐文件列表界面 一个音乐文件列表界面:主要1负责展示音乐 ...

  2. Android课设:简易音乐播放器

    实验主题 本次课程设计计划实现一个低配版的仿网易云音乐的音乐播放器,主要实现功能如下: 打开APP需先进行注册 已有账号可进行登录 登录后跳转至音乐界面,本地歌曲列表读取本地音乐文件并显示 点击本地音 ...

  3. C++ 制作简易音乐播放器

    内容 利用c++以及一些函数库制作一个简单的音乐播放器. 成果: 实现了:打开一个音频文件,播放音频,中途暂停或继续,停止换歌,滑动控制音量大小. 视频教程 本人也是根据视频教程所学,内容相同.可点击 ...

  4. MFC制作简易音乐播放器

    // MFC音乐播放器Dlg.cpp : implementation file // #include "stdafx.h" #include "MFC音乐播放器.h& ...

  5. 用Vue制作简易音乐播放器(超详细)

    先放个效果图吧 首先先把主体结构搭好,样式调好,然后再来写播放器的功能. 根据播放器的形状,将其分为头部(搜索栏),中间(歌曲列表,碟片,热评),尾部(播放器栏),html结构如下 <div c ...

  6. QT——制作简易音频播放器

    应用前提:只需要从阿里云数据库中读取选定的某一条实验数据的音频(.wav),现在的测试版本只是播放本地音频,所以做的这个音频播放器只有6个功能:播放.暂停.音量条.静音.进度条.显示当前播放进度的时间 ...

  7. Android Studio简易音乐播放器设计作业

    Android Studio简易音乐播放器设计作业 实验成功展示 实验代码 MainActivity.java XML文件 class文件 利用BroadcastReceiver模拟音乐播放器,实现播 ...

  8. Android制作简易的调色器,并实现复制色值的功能

    Android制作简易的调色器,并实现复制色值的功能 我们上课老师让做的作业,参照别人的代码,可能不够完善,请大家见谅- 主要用到SeekBar控件 先展示效果图吧 点击复制的Button,弹出提示信 ...

  9. 第8章系统服务(简易音频播放器的实现)

    开发一个简易音乐播放器,要求实现: 综合使用Service,BroadCast,ContentProvider等组件实现后台播放. 播放和暂停.上一首.下一首.停止: 后台播放功能, 按下返回键退出应 ...

最新文章

  1. next_permutation(,)用法
  2. 一个实体对象不能由多个 IEntityChangeTracker 实例引用
  3. java 堆栈 对象_在Java中,哪些对象放在堆栈上,哪些放在堆上?
  4. 202701算法_冒泡排序
  5. php 获取网卡mac
  6. [转]ES7、ES8、ES9、ES10新特性大盘点
  7. 1005 继续(3n+1)猜想(25 分)
  8. C++智能指针与动态内存分配
  9. 设计模式精髓—封装变化
  10. (day 52 - 递归 and 短路逻辑运算符的用法 ) 剑指 Offer 64. 求1+2+…+n
  11. objective-C语言:第一个OC程序
  12. 1688接口:item_search - 按关键字搜索商品
  13. tof摄像头手势识别_全面解析深度摄像头(TOF Camera)的原理
  14. 如何解决 CAD 启动非常慢的问题
  15. 先将输入的一系列整数中的最小值与第一个数交换,然后将最大值与最后一个数交换,最后输出交换后的序列。
  16. 让你百分百玩转抖音!
  17. 云机器被渗透了怎么办以及解决方法!
  18. 鼠绘-汽车侧面绘制过程
  19. 汇编语言——跳转指令: JMP、JECXZ、JA、JB、JG、JL、JE、JZ、JS、JC、JO、JP
  20. STM32基础(11)光敏传感

热门文章

  1. 实际操作_MFC修改控件的Tab顺序
  2. ssm查询一条数据并显示_高亮显示查询数据,其实很简单
  3. td里面字体大小怎么改_王者荣耀战区怎么改到其他地方 2020荣耀战区修改方法...
  4. linux命令学习之 cp(命令学习之四)
  5. 数据结构和算法-001 数组
  6. android sqlite 怎么写入存储时间
  7. Android的Activity屏幕切换动画(一)-左右滑动切换
  8. AgileEAS.NET平台开发实例-药店系统-准备开发环境(上)
  9. ubuntu10.04 的服务管理变动
  10. 如何在windows xp下使用ntfs权限控制