Android应用开发 MP3音乐播放器代码实现 二

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

Android应用开发--MP3音乐播放器代码实现(二)

 

2013年5月25日 简、美音乐播放器开发

小巫在这里罗列这个播放器已经实现的功能:

1.   自动显示音乐列表

2.   点击列表播放音乐

3.   长按列表弹出对话框

4.   暂停音乐

5.   上一首音乐

6.   下一首音乐

7.   自动播放下一首歌曲

8.   单曲循环

9.   全部循环

10.  随机播放

 

以上所有功能将会分为两篇博文来讲解,首先是主界面的,接着是播放界面的。在这里要说明一点,以上功能是小巫自己一点一点调试才实现的,并不能完全排除考虑不周的地方,原本这个软件实现起来并不太难,但确实要考虑到很多细节的地方,播放状态的切换和控制就是一块,也花了我不少实现,之前还很苦恼实现自己想要的效果,但后来还是经过思考和调试把功能实现。所以说,开发是一个需要很耐心的过程,各位童鞋,如果真正喜欢编程的话,想要做出一些小作品的话,那就好好掂量自己的耐心吧,好了,废话不多说,先贴一大段代码,后面在慢慢把需要注意的地方说一下。

主界面效果图:

            

以上界面的效果怎么实现的?

很简单的,就是ListView的数据填充,但要填的的东西就要考虑了,怎么把数据从SQLite中获取,小巫封装了一个工具类,用来获取与MP3相关的数据。

==>MediaUtils

package com.wwj.sb.utils;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import android.content.Context;import android.database.Cursor;import android.provider.MediaStore;import com.wwj.sb.domain.Mp3Info;public class MediaUtil /**  * 用于从数据库中查询歌曲的信息,保存在List当中  *   * @return  */ public static List<Mp3Info> getMp3Infos(Context context) {  Cursor cursor = context.getContentResolver().query(    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,    MediaStore.Audio.Media.DEFAULT_SORT_ORDER);  List<Mp3Info> mp3Infos = new ArrayList<Mp3Info>();  for (int i = 0; i < cursor.getCount(); i++) {   cursor.moveToNext();   Mp3Info mp3Info = new Mp3Info();   long id = cursor.getLong(cursor     .getColumnIndex(MediaStore.Audio.Media._ID));    //音乐id   String title = cursor.getString((cursor      .getColumnIndex(MediaStore.Audio.Media.TITLE)));   //音乐标题   String artist = cursor.getString(cursor     .getColumnIndex(MediaStore.Audio.Media.ARTIST));   //艺术家   long duration = cursor.getLong(cursor     .getColumnIndex(MediaStore.Audio.Media.DURATION));   //时长   long size = cursor.getLong(cursor     .getColumnIndex(MediaStore.Audio.Media.SIZE));    //文件大小   String url = cursor.getString(cursor     .getColumnIndex(MediaStore.Audio.Media.DATA));    //文件路径   int isMusic = cursor.getInt(cursor     .getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));   //是否为音乐   if (isMusic != 0) {  //只把音乐添加到集合当中    mp3Info.setId(id);    mp3Info.setTitle(title);    mp3Info.setArtist(artist);    mp3Info.setDuration(duration);    mp3Info.setSize(size);    mp3Info.setUrl(url);    mp3Infos.add(mp3Info);   }  }  return mp3Infos; }  /**  * 往List集合中添加Map对象数据,每一个Map对象存放一首音乐的所有属性  * @param mp3Infos  * @return  */ public static List<HashMap<String, String>> getMusicMaps(   List<Mp3Info> mp3Infos) {  List<HashMap<String, String>> mp3list = new ArrayList<HashMap<String, String>>();  for (Iterator iterator = mp3Infos.iterator(); iterator.hasNext();) {   Mp3Info mp3Info = (Mp3Info) iterator.next();   HashMap<String, String> map = new HashMap<String, String>();   map.put("title", mp3Info.getTitle());   map.put("Artist", mp3Info.getArtist());   map.put("duration", formatTime(mp3Info.getDuration()));   map.put("size", String.valueOf(mp3Info.getSize()));   map.put("url", mp3Info.getUrl());   mp3list.add(map);  }  return mp3list; }  /**  * 格式化时间,将毫秒转换为分:秒格式  * @param time  * @return  */ public static String formatTime(long time) {  String min = time / (1000 * 60) + "";  String sec = time % (1000 * 60) + "";  if (min.length() < 2) {   min = "0" + time / (1000 * 60) + "";  } else {   min = time / (1000 * 60) + "";  }  if (sec.length() == 4) {   sec = "0" + (time % (1000 * 60)) + "";  } else if (sec.length() == 3) {   sec = "00" + (time % (1000 * 60)) + "";  } else if (sec.length() == 2) {   sec = "000" + (time % (1000 * 60)) + "";  } else if (sec.length() == 1) {   sec = "0000" + (time % (1000 * 60)) + "";  }  return min + ":" + sec.trim().substring(0, 2); }}


好吧,来重头戏了,一大段代码来袭。

HomeActivity.Java

package com.wwj.sb.activity;import java.util.HashMap;import java.util.List;import android.app.Activity;import android.app.AlertDialog;import android.app.Service;import android.content.BroadcastReceiver;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.IntentFilter;import android.graphics.Color;import android.os.Bundle;import android.os.Vibrator;import android.view.ContextMenu;import android.view.ContextMenu.ContextMenuInfo;import android.view.KeyEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnCreateContextMenuListener;import android.view.ViewGroup.LayoutParams;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ImageView;import android.widget.ListView;import android.widget.SimpleAdapter;import android.widget.TextView;import android.widget.Toast;import com.wwj.sb.domain.AppConstant;import com.wwj.sb.domain.Mp3Info;import com.wwj.sb.service.PlayerService;import com.wwj.sb.utils.ConstantUtil;import com.wwj.sb.utils.CustomDialog;import com.wwj.sb.utils.MediaUtil;/** * 2013/5/7 * 简、美音乐播放器 * @author wwj *  */public class HomeActivity extends Activity private ListView mMusiclist; // 音乐列表 private List<Mp3Info> mp3Infos = nullprivate SimpleAdapter mAdapter; // 简单适配器 private Button previousBtn; // 上一首 private Button repeatBtn; // 重复(单曲循环、全部循环) private Button playBtn; // 播放(播放、暂停) private Button shuffleBtn; // 随机播放 private Button nextBtn; // 下一首 private TextView musicTitle;//歌曲标题 private TextView musicDuration; //歌曲时间 private Button musicPlaying; //歌曲专辑 private int repeatState;  //循环标识 private final int isCurrentRepeat = 1; // 单曲循环 private final int isAllRepeat = 2; // 全部循环 private final int isNoneRepeat = 3; // 无重复播放 private boolean isFirstTime = true;  private boolean isPlaying; // 正在播放 private boolean isPause; // 暂停 private boolean isNoneShuffle = true; // 顺序播放 private boolean isShuffle = false; // 随机播放   private int listPosition = 0//标识列表位置 private HomeReceiver homeReceiver; //自定义的广播接收器 //一系列动作 public static final String UPDATE_ACTION = "com.wwj.action.UPDATE_ACTION"public static final String CTL_ACTION = "com.wwj.action.CTL_ACTION"public static final String MUSIC_CURRENT = "com.wwj.action.MUSIC_CURRENT"public static final String MUSIC_DURATION = "com.wwj.action.MUSIC_DURATION"public static final String REPEAT_ACTION = "com.wwj.action.REPEAT_ACTION"public static final String SHUFFLE_ACTION = "com.wwj.action.SHUFFLE_ACTION";   private int currentTime; private int duration; @Override public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.home_activity_layout);  mMusiclist = (ListView) findViewById(R.id.music_list);  mMusiclist.setOnItemClickListener(new MusicListItemClickListener());  mMusiclist.setOnCreateContextMenuListener(new MusicListItemContextMenuListener());  mp3Infos = MediaUtil.getMp3Infos(getApplicationContext()); //获取歌曲对象集合  setListAdpter(MediaUtil.getMusicMaps(mp3Infos)); //显示歌曲列表  findViewById();    //找到界面上的每一个控件  setViewOnclickListener(); //为一些控件设置监听器  repeatState = isNoneRepeat; // 初始状态为无重复播放状态      homeReceiver = new HomeReceiver();  // 创建IntentFilter  IntentFilter filter = new IntentFilter();  // 指定BroadcastReceiver监听的Action  filter.addAction(UPDATE_ACTION);  filter.addAction(MUSIC_CURRENT);  filter.addAction(MUSIC_DURATION);  filter.addAction(REPEAT_ACTION);  filter.addAction(SHUFFLE_ACTION);  // 注册BroadcastReceiver  registerReceiver(homeReceiver, filter);   } /**  * 从界面上根据id获取按钮  */ private void findViewById() {  previousBtn = (Button) findViewById(R.id.previous_music);  repeatBtn = (Button) findViewById(R.id.repeat_music);  playBtn = (Button) findViewById(R.id.play_music);  shuffleBtn = (Button) findViewById(R.id.shuffle_music);  nextBtn = (Button) findViewById(R.id.next_music);  musicTitle = (TextView) findViewById(R.id.music_title);  musicDuration = (TextView) findViewById(R.id.music_duration);  musicPlaying = (Button) findViewById(R.id.playing); } /**  * 给每一个按钮设置监听器  */ private void setViewOnclickListener() {  ViewOnClickListener viewOnClickListener = new ViewOnClickListener();  previousBtn.setOnClickListener(viewOnClickListener);  repeatBtn.setOnClickListener(viewOnClickListener);  playBtn.setOnClickListener(viewOnClickListener);  shuffleBtn.setOnClickListener(viewOnClickListener);  nextBtn.setOnClickListener(viewOnClickListener);  musicPlaying.setOnClickListener(viewOnClickListener); } private class ViewOnClickListener implements OnClickListener {  Intent intent = new Intent();  @Override  public void onClick(View v) {   switch (v.getId()) {   case R.id.previous_music: // 上一首    playBtn.setBackgroundResource(R.drawable.play_selector);    isFirstTime = false;    isPlaying = true;    isPause = false;    previous();    break;   case R.id.repeat_music: // 重复播放    if (repeatState == isNoneRepeat) {     repeat_one();     shuffleBtn.setClickable(false);     repeatState = isCurrentRepeat;    } else if (repeatState == isCurrentRepeat) {     repeat_all();     shuffleBtn.setClickable(false);     repeatState = isAllRepeat;    } else if (repeatState == isAllRepeat) {     repeat_none();     shuffleBtn.setClickable(true);     repeatState = isNoneRepeat;    }    switch (repeatState) {    case isCurrentRepeat: // 单曲循环     repeatBtn       .setBackgroundResource(R.drawable.repeat_current_selector);     Toast.makeText(HomeActivity.this, R.string.repeat_current,       Toast.LENGTH_SHORT).show();     break;    case isAllRepeat: // 全部循环     repeatBtn       .setBackgroundResource(R.drawable.repeat_all_selector);     Toast.makeText(HomeActivity.this, R.string.repeat_all,       Toast.LENGTH_SHORT).show();     break;    case isNoneRepeat: // 无重复     repeatBtn       .setBackgroundResource(R.drawable.repeat_none_selector);     Toast.makeText(HomeActivity.this, R.string.repeat_none,       Toast.LENGTH_SHORT).show();     break;    }    break;   case R.id.play_music: // 播放音乐    if(isFirstTime) {     play();     isFirstTime = false;     isPlaying = true;     isPause = false;    } else {     if (isPlaying) {      playBtn.setBackgroundResource(R.drawable.pause_selector);      intent.setAction("com.wwj.media.MUSIC_SERVICE");      intent.putExtra("MSG", AppConstant.PlayerMsg.PAUSE_MSG);      startService(intent);      isPlaying = false;      isPause = true;           } else if (isPause) {      playBtn.setBackgroundResource(R.drawable.play_selector);      intent.setAction("com.wwj.media.MUSIC_SERVICE");      intent.putExtra("MSG", AppConstant.PlayerMsg.CONTINUE_MSG);      startService(intent);      isPause = false;      isPlaying = true;     }    }    break;   case R.id.shuffle_music: // 随机播放    if (isNoneShuffle) {     shuffleBtn       .setBackgroundResource(R.drawable.shuffle_selector);     Toast.makeText(HomeActivity.this, R.string.shuffle,       Toast.LENGTH_SHORT).show();     isNoneShuffle = false;     isShuffle = true;     shuffleMusic();     repeatBtn.setClickable(false);    } else if (isShuffle) {     shuffleBtn       .setBackgroundResource(R.drawable.shuffle_none_selector);     Toast.makeText(HomeActivity.this, R.string.shuffle_none,       Toast.LENGTH_SHORT).show();     isShuffle = false;     isNoneShuffle = true;     repeatBtn.setClickable(true);    }    break;   case R.id.next_music: // 下一首    playBtn.setBackgroundResource(R.drawable.play_selector);    isFirstTime = false;    isPlaying = true;    isPause = false;    next();    break;   case R.id.playing: //正在播放    Mp3Info mp3Info = mp3Infos.get(listPosition);    Intent intent = new Intent(HomeActivity.this, PlayerActivity.class);    intent.putExtra("title", mp3Info.getTitle());     intent.putExtra("url", mp3Info.getUrl());    intent.putExtra("artist", mp3Info.getArtist());    intent.putExtra("listPosition", listPosition);    intent.putExtra("currentTime", currentTime);    intent.putExtra("duration", duration);    intent.putExtra("MSG", AppConstant.PlayerMsg.PLAYING_MSG);    startActivity(intent);    break;   }  } } private class MusicListItemClickListener implements OnItemClickListener {  /**   * 点击列表播放音乐   */  @Override  public void onItemClick(AdapterView<?> parent, View view, int position,    long id) {   listPosition = position;   playMusic(listPosition);    } }  public class MusicListItemContextMenuListener implements OnCreateContextMenuListener {  @Override  public void onCreateContextMenu(ContextMenu menu, View v,    ContextMenuInfo menuInfo) {   Vibrator vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);   vibrator.vibrate(50);   //长按振动   musicListItemDialog();  //长按后弹出的对话框  } } /**  * 填充列表  *   * @param mp3Infos  */ public void setListAdpter(List<HashMap<String, String>> mp3list) {  mAdapter = new SimpleAdapter(this, mp3list,    R.layout.music_list_item_layout, new String[] { "title",      "Artist", "duration" }, new int[] { R.id.music_title,      R.id.music_Artist, R.id.music_duration });  mMusiclist.setAdapter(mAdapter); }   /**  * 下一首歌曲  */ public void next() {  listPosition = listPosition + 1;  if(listPosition <= mp3Infos.size() - 1) {   Mp3Info mp3Info = mp3Infos.get(listPosition);   musicTitle.setText(mp3Info.getTitle());   Intent intent = new Intent();   intent.setAction("com.wwj.media.MUSIC_SERVICE");   intent.putExtra("listPosition", listPosition);   intent.putExtra("url", mp3Info.getUrl());   intent.putExtra("MSG", AppConstant.PlayerMsg.NEXT_MSG);   startService(intent);  } else {   Toast.makeText(HomeActivity.this, "没有下一首了", Toast.LENGTH_SHORT).show();  } } /**  * 上一首歌曲  */ public void previous() {  listPosition = listPosition - 1;  if(listPosition >= 0) {   Mp3Info mp3Info = mp3Infos.get(listPosition);   musicTitle.setText(mp3Info.getTitle());   Intent intent = new Intent();   intent.setAction("com.wwj.media.MUSIC_SERVICE");   intent.putExtra("listPosition", listPosition);   intent.putExtra("url", mp3Info.getUrl());   intent.putExtra("MSG", AppConstant.PlayerMsg.PRIVIOUS_MSG);   startService(intent);  }else {   Toast.makeText(HomeActivity.this, "没有上一首了", Toast.LENGTH_SHORT).show();  } } public void play() {  playBtn.setBackgroundResource(R.drawable.play_selector);  Mp3Info mp3Info = mp3Infos.get(listPosition);  musicTitle.setText(mp3Info.getTitle());  Intent intent = new Intent();  intent.setAction("com.wwj.media.MUSIC_SERVICE");  intent.putExtra("listPosition", 0);  intent.putExtra("url", mp3Info.getUrl());  intent.putExtra("MSG", AppConstant.PlayerMsg.PLAY_MSG);  startService(intent); }  /**  * 单曲循环  */ public void repeat_one() {  Intent intent = new Intent(CTL_ACTION);  intent.putExtra("control", 1);  sendBroadcast(intent); }  /**  * 全部循环  */ public void repeat_all() {  Intent intent = new Intent(CTL_ACTION);  intent.putExtra("control", 2);  sendBroadcast(intent); } /**  * 顺序播放  */ public void repeat_none() {  Intent intent = new Intent(CTL_ACTION);  intent.putExtra("control", 3);  sendBroadcast(intent); }  /**  * 随机播放  */ public void shuffleMusic() {  Intent intent = new Intent(CTL_ACTION);  intent.putExtra("control", 4);  sendBroadcast(intent); } public void musicListItemDialog() {  String[] menuItems = new String[]{"播放音乐","设为铃声","查看详情"};  ListView menuList = new ListView(HomeActivity.this);  menuList.setCacheColorHint(Color.TRANSPARENT);  menuList.setDividerHeight(1);  menuList.setAdapter(new ArrayAdapter<String>(HomeActivity.this, R.layout.context_dialog_layout, R.id.dialogText, menuItems));  menuList.setLayoutParams(new LayoutParams(ConstantUtil.getScreen(HomeActivity.this)[0] / 2, LayoutParams.WRAP_CONTENT));      final CustomDialog customDialog = new CustomDialog.Builder(HomeActivity.this).setTitle(R.string.operation).setView(menuList).create();  customDialog.show();    menuList.setOnItemClickListener( new OnItemClickListener() {   @Override   public void onItemClick(AdapterView<?> parent, View view,     int position, long id) {    customDialog.cancel();    customDialog.dismiss();   }     }); } public void playMusic(int listPosition) {  if (mp3Infos != null) {   Mp3Info mp3Info = mp3Infos.get(listPosition);   musicTitle.setText(mp3Info.getTitle());   Intent intent = new Intent(HomeActivity.this, PlayerActivity.class);   intent.putExtra("title", mp3Info.getTitle());    intent.putExtra("url", mp3Info.getUrl());   intent.putExtra("artist", mp3Info.getArtist());   intent.putExtra("listPosition", listPosition);   intent.putExtra("currentTime", currentTime);   intent.putExtra("repeatState", repeatState);   intent.putExtra("shuffleState", isShuffle);   intent.putExtra("MSG", AppConstant.PlayerMsg.PLAY_MSG);   startActivity(intent);  } }  @Override protected void onStop() {  // TODO Auto-generated method stub  super.onStop(); }   @Override protected void onDestroy() {  // TODO Auto-generated method stub  super.onDestroy(); }  /**  * 按返回键弹出对话框确定退出  */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) {  if (keyCode == KeyEvent.KEYCODE_BACK    && event.getAction() == KeyEvent.ACTION_DOWN) {   new AlertDialog.Builder(this)     .setIcon(R.drawable.ic_launcher)     .setTitle("退出")     .setMessage("您确定要退出?")     .setNegativeButton("取消", null)     .setPositiveButton("确定",       new DialogInterface.OnClickListener() {        @Override        public void onClick(DialogInterface dialog,          int which) {         finish();         Intent intent = new Intent(           HomeActivity.this,           PlayerService.class);         unregisterReceiver(homeReceiver);         stopService(intent); // 停止后台服务        }       }).show();  }  return super.onKeyDown(keyCode, event); }   //自定义的BroadcastReceiver,负责监听从Service传回来的广播 public class HomeReceiver extends BroadcastReceiver {  @Override  public void onReceive(Context context, Intent intent) {   String action = intent.getAction();    if(action.equals(MUSIC_CURRENT)){    //currentTime代表当前播放的时间    currentTime = intent.getIntExtra("currentTime", -1);    musicDuration.setText(MediaUtil.formatTime(currentTime));   } else if (action.equals(MUSIC_DURATION)) {    duration = intent.getIntExtra("duration", -1);   }   else if(action.equals(UPDATE_ACTION)) {    //获取Intent中的current消息,current代表当前正在播放的歌曲    listPosition = intent.getIntExtra("current", -1);    if(listPosition >= 0) {     musicTitle.setText(mp3Infos.get(listPosition).getTitle());    }   }else if(action.equals(REPEAT_ACTION)) {    repeatState = intent.getIntExtra("repeatState", -1);    switch (repeatState) {    case isCurrentRepeat: // 单曲循环     repeatBtn       .setBackgroundResource(R.drawable.repeat_current_selector);     shuffleBtn.setClickable(false);     break;    case isAllRepeat: // 全部循环     repeatBtn       .setBackgroundResource(R.drawable.repeat_all_selector);     shuffleBtn.setClickable(false);     break;    case isNoneRepeat: // 无重复     repeatBtn       .setBackgroundResource(R.drawable.repeat_none_selector);     shuffleBtn.setClickable(true);     break;    }   }   else if(action.equals(SHUFFLE_ACTION)) {    isShuffle = intent.getBooleanExtra("shuffleState", false);    if(isShuffle) {     isNoneShuffle = false;     shuffleBtn.setBackgroundResource(R.drawable.shuffle_selector);     repeatBtn.setClickable(false);    } else {     isNoneShuffle = true;     shuffleBtn.setBackgroundResource(R.drawable.shuffle_none_selector);     repeatBtn.setClickable(true);    }   }  }   }}


到这里,要开讲啦。

以下是需要注意的几点:

1. 音乐是通过Service来播放的,Activity通过启动服务来实现在后台播放音乐。

2. Activity中自定义了一个广播接收器,需要进行intent过滤器的定义,动作的添加,注册广播接收器:

  homeReceiver = new HomeReceiver();  // 创建IntentFilter  IntentFilter filter = new IntentFilter();  // 指定BroadcastReceiver监听的Action  filter.addAction(UPDATE_ACTION);  filter.addAction(MUSIC_CURRENT);  filter.addAction(MUSIC_DURATION);  filter.addAction(REPEAT_ACTION);  filter.addAction(SHUFFLE_ACTION);  // 注册BroadcastReceiver  registerReceiver(homeReceiver, filter);  


3. 在广播接收器类当中对动作进行处理,比如实现时间的更新和标题的更新等。

4. 这里还要注意按钮触发,播放状态的改变,比如音乐循环,有三种状态:单曲、全部循环、顺序,每切换一个状态都要向服务发送一条广播,通知它要改变状态。

5. 点击列表的时候,会跳入到播放界面的Activity中,要注意用intent来传递参数,注意每个参数的用途,比如title、url、MSG,就分别代表标题、路径、播放状态。

6. 长按列表会弹出自定义对话框,也会有短暂的震动效果,自定义对话框需要自行实现。这里我也贴一下实现代码吧。

package com.wwj.sb.utils;import android.app.Activity;import android.app.Dialog;import android.content.Context;import android.content.DialogInterface;import android.text.TextUtils;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.ViewGroup.LayoutParams;import android.widget.Button;import android.widget.FrameLayout;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import com.wwj.sb.activity.R;/** * 自定义对话框类 *  * @author wwj *  */public class CustomDialog extends Dialog public CustomDialog(Context context) {  super(context); } public CustomDialog(Context context, int theme) {  super(context, theme); } public static class Builder {  private Context context;  private int mIcon = -1; // 提示图标  private CharSequence mTitle; // 提示标题  private CharSequence mMessage; // 提示内容  private CharSequence mPositiveButtonText; // 确定按钮文本  private CharSequence mNegativeButtonText; // 取消按钮文本  private CharSequence mNeutralButtonText; // 中间按钮文本  private boolean mCancelable = true; // 是否启用取消键  private int mViewSpacingLeft;  private int mViewSpacingTop;  private int mViewSpacingRight;  private int mViewSpacingBottom;  private boolean mViewSpacingSpecified = false;  // 提示内容View  private
给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值