天天看点

第二次作业——Service、Listview与ACtivity参数传递源代码点击此处下载

转载请注明出处:http://blog.csdn.net/qq347198688/article/details/52914407

本文出自【何嘉龙的博客】

前言

在实战之前呢,我想跟大家唠唠几句,本来在老师刚布置下来答案的时候,我就想给大家把作业完成,然后分享出来。但是,实在是有点脱不开身,最近有点忙,加上大三的课程跟实验也多。今天好不容易空了半天时间出来,我就立马打开我的博客,准备写一篇分享第二次作业的文章。嘿嘿,其中,让我看到一件很开心的事情,那就是我第一次作业的博客访问量突破两百了,成为我博客里面访问量暂时最高的一篇(ps:虽然很少),而且还有一位同学评论了,非常感谢。我想这也是对于我最大的支持与鼓励吧,也欢迎大家多指责我博客的不足的地方。

作业要求:

  1. 如下图列表显示三首歌曲的歌名、歌手名和封面
  2. 点击列表项使用service播放对应歌曲
  3. 点击列表项跳转至另一Activity显示对应歌词
  4. 可用控制按钮控制播放过程(播放、暂停、停止)
  5. 调试并运行程序,并在作业平台提交该项目工程目录的压缩包和运行效果截图。

注意事项:

  1. Application name统一命名为job2,Company Domain统一命名为“姓名全拼.whut.edu”(如qinposhi.whut.edu)
  2. 相关资源(封面图片、按钮图标、歌曲)直接放到项目的资源目录下,歌词可直接放到源代码中。(不限使用我提供的资源,大家可自行选择资源)
  3. 项目工程目录的压缩包统一命名为“学号姓名作业1.rar”(如100000000_秦珀石_作业1.rar).
  4. 作业的具体要求和相关资源可在教学资源中的作业要求目录中去查找(界面原型需安装mockplus,安装包也在目录中)

作业实战:

首先,让我们新建一个工程job2,公司域名(company domain)为“姓名全拼.whut.edu”。然后看到作业要求,我们看到主页面:

第二次作业——Service、Listview与ACtivity参数传递源代码点击此处下载

首先看到最后一行三个按钮,这三个按钮水平排列成一行,而且三个按钮均分了最后一行,所以这里我们考虑用LinearLayout的水平排列。再看到上面三行的样式是一样的,所以我们考虑用ListView/RecylerView来写,我们这里用ListView实现更加简单,所以决定采用ListView。因此我们的布局文件activity_main.xml文件可以这样写:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <ListView
        android:id="@+id/list_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:divider="#000"
        android:dividerHeight="1dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:gravity="center_horizontal"
        android:orientation='horizontal'>

        <ImageButton
            android:id="@+id/play"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:background="@drawable/btn_selector"
            android:src="@drawable/play" />

        <ImageButton
            android:id="@+id/pause"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:background="@drawable/btn_selector"
            android:src="@drawable/pause" />

        <ImageButton
            android:id="@+id/stop"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:background="@drawable/btn_selector"
            android:src="@drawable/stop" />
    </LinearLayout>
</LinearLayout>
           

这里我们还需要说几个地方,ListView的分割线的默认样式是灰色的,不太显眼,所以我们把分割线的颜色改为黑色,也就是加上

android:divider="#000"

代码,但是这个时候如果我们已经写好了ListView的相关代码,运行程序可以发现,咦,分割线怎么没了?是这样的,如果我们不加分割线的相关代码,ListView就会采用默认的分割线,有颜色还有高度。但是如果我们自己加了分割线,ListView就会使用我们的分割线,我们没有指定

android:dividerHeight="1dp"

,没有高度,那分割线肯定就看不到了。另外,我们为了让三个按钮平分一行,需要用到

android:layout_weight

,layout_weight是权重,我们需要把宽度等分,所以,先要把宽度设为

android:layout_width="0dp"

,另外

android:layout_weight="1"

,这样三个按钮在宽度上就等分了。当然,我们需要先把老师给的三个按钮的图标放在drawable目录下。最后一个要说的地方就是,眼尖的同学可能看到了

android:background="@drawable/btn_selector"

这行代码。我们需要在drawable目录下,新建一个Drawable resource file,名字为btn_selector,父元素Root Element为selector,顾名思义,这是一个按钮选择器,目的是为了让我们点击按钮的时候有点击效果。btn_selector.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@color/colorAccent"/>
</selector>
           

写完了三个按钮,我们就要重新看到ListView的条目了,每个条目里面包括一个图片,歌曲的名字,歌手的名字。我们在layout目录下新建一个Layout resource file,名字为icon_list,里面的代码如下:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="130dp">

    <ImageView
        android:layout_marginLeft="10dp"
        android:id="@+id/image"
        android:layout_width="120dp"
        android:layout_height="100dp"
        android:layout_centerVertical="true"
        android:adjustViewBounds="true"
        android:padding="2dip"
        android:scaleType="fitXY" />

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/image"
        android:layout_marginLeft="10dp"
        android:layout_alignTop="@id/image"
        android:ellipsize="marquee"
        android:textColor="#000"
        android:textSize="20dip" />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/image"
        android:layout_alignBottom="@id/image"
        android:layout_alignLeft="@id/title"
        android:gravity="center_vertical"
        android:textColor="#000"
        android:textSize="24dip" />

</RelativeLayout>
           

这个布局文件,我想我不用细讲吧,就算我想讲,估计也得要写一篇新博客才能说得明白。这个不懂的同学可以去看一下网上的五大布局的文档。

在主页面的布局文件搭建好之后,我们就要看到java代码部分了,先把服务Service代码写完,我直接复制的老师的Sample里面的BindMusicPlayerService.java文件。这里需要注意的是,四大组件如果要使用,都需要在AndroidManifest.xml文件中配置,这里我们要配置

<service android:name=".BindMusicPlayerService"> </service>

代码如下所示:

package edu.whut.xucheng.job2;

import android.app.Service;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;

public class BindMusicPlayerService extends Service {
    private MediaPlayer mediaPlayer;

    private final IBinder binder = new MyBinder();
    int[] Mp3List = {R.raw.m1, R.raw.m2, R.raw.m3};

    public class MyBinder extends Binder {

        BindMusicPlayerService getService() {
            return BindMusicPlayerService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        super.dump(fd, writer, args);
    }


    @Override
    protected void finalize() throws Throwable {
        super.finalize();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            mediaPlayer.release();
        }
    }

    public void play(int num) {
        mediaPlayer = MediaPlayer.create(this, Mp3List[num]);
        mediaPlayer.setLooping(false);
        if (!mediaPlayer.isPlaying()) {
            mediaPlayer.start();
        }
    }

    public void replay() {
        if (mediaPlayer == null) {
            mediaPlayer = MediaPlayer.create(this, Mp3List[]);
            mediaPlayer.setLooping(false);
        }
        if (!mediaPlayer.isPlaying()) {
            mediaPlayer.start();
        }
    }

    public void pause() {
        if (mediaPlayer.isPlaying() && mediaPlayer != null) {
            mediaPlayer.pause();
        }
    }

    public void stop() {
        if (mediaPlayer != null) {
            mediaPlayer.stop();
            try {
                mediaPlayer.prepare();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
           

写完了服务的代码后,准确地说是Copy完,我们继续写MainActivity的代码,MainActivity主要是为了实现与Service交互,这里我们需要把老师给的歌曲文件放在一个raw目录下,raw目录需要自己在res目录下新建。MainActivity代码如下:

package edu.whut.xucheng.job2;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String NUMBER = "num";

    /**
     * 播放按钮
     */
    private ImageButton play;

    /**
     * 暂停按钮
     */
    private ImageButton pause;

    /**
     * 停止按钮
     */
    private ImageButton stop;

    /**
     * 音乐播放器服务的对象
     */
    private BindMusicPlayerService bindMusicPlayerService;

    /**
     * 需要显示的数据
     */
    private String[] mName = {"俾面派对", "富士山下", "无心睡眠"};
    private String[] mSinger = {"BEYOND", "陈奕迅", "张国荣"};
    private Integer[] cover = {R.drawable.c1, R.drawable.c2, R.drawable.c3};

    /**
     * ListView的对象
     */
    private ListView mListView;

    /**
     * ArrayList的对象,用于存放listView展示的数据
     */
    ArrayList<Map<String, Object>> mData = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        init();
        showListView();

        //position为当前点击的条目所对应的数字,比如点击的第一个条目,对应的position就是0,以此类推
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                Intent intent = new Intent(MainActivity.this, LyricsActivity.class);
                //把当前点击的条目对应的数字传给LyricsActivity
                intent.putExtra(NUMBER, position);
                startActivity(intent);
                //播放歌曲
                bindMusicPlayerService.stop();
                bindMusicPlayerService.play(position);
            }
        });

    }

    /**
     * 将存放在ArrayList里面的数据展示出来,其中image为图片,title为歌名,text为歌手名
     */
    private void showListView() {
        SimpleAdapter adapter = new SimpleAdapter(this, mData, R.layout.icon_list,
                new String[]{"image", "title", "text"}, new int[]{R.id.image, R.id.title, R.id.text});
        mListView.setAdapter(adapter);
    }

    /**
     * 将MainActivity跟Service绑定起来
     */
    private void init() {
        Intent s = new Intent(MainActivity.this, BindMusicPlayerService.class);
        bindService(s, connection, Context.BIND_AUTO_CREATE);
    }

    /**
     * 初始化数据,把数据存入ArrayList中,其中put(key, value)函数中,
     * key对应的是键值,value对应的是值,key跟value是唯一对应关系,根据key来查找value。
     */
    private void initData() {
        int length = mName.length;
        for (int i = ; i < length; i++) {
            Map<String, Object> item = new HashMap<>();
            item.put("image", cover[i]);
            item.put("title", mName[i]);
            item.put("text", mSinger[i]);
            mData.add(item);
        }
    }

    /**
     * 初始化View
     */
    private void initView() {
        mListView = (ListView) this.findViewById(R.id.list_item);
        play = (ImageButton) this.findViewById(R.id.play);
        pause = (ImageButton) this.findViewById(R.id.pause);
        stop = (ImageButton) this.findViewById(R.id.stop);
        play.setOnClickListener(this);
        pause.setOnClickListener(this);
        stop.setOnClickListener(this);
    }

    /**
     * 处理点击事件
     */
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            //播放
            case R.id.play:
                bindMusicPlayerService.replay();
                break;
            //暂停
            case R.id.pause:
                bindMusicPlayerService.pause();
                break;
            //停止
            case R.id.stop:
                bindMusicPlayerService.stop();
                break;
        }
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            bindMusicPlayerService = ((BindMusicPlayerService.MyBinder) service).getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            bindMusicPlayerService = null;
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        this.unbindService(connection);
    }
}
           

在写完了主页面之后,点击ListView的条目会跳转到LyricsActivity,也就是歌词界面。我们先看下作业的要求:

第二次作业——Service、Listview与ACtivity参数传递源代码点击此处下载

我们可以看到的是,歌词水平居中,只有文字,而且是可以滑动的。因此我们可以在layout文件夹下面新建activity_lyrics.xml文件,activity_lyrics.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/lyrics"
        android:textSize="16sp"
        android:textColor="#000"
        android:gravity="center_horizontal"
        android:layout_width="match_parent"
        android:scrollbars="vertical"
        android:layout_height="wrap_content" />

</ScrollView>
           

大家看到这个xml文件的根布局是不是有点奇怪,我们一般接触到的都是五大布局,LinearLayout,RelativeLayout什么的,这次看到最外面是ScrollView。我查看过源代码,ScrollView是继承自ViewParent的,而ViewParent里面可以嵌套ViewParent跟View,所以ScrollView可以放在最外面作为根布局,我们甚至都可以自己写一个View继承自ViewParent然后放在根布局。使用ScrollView的效果就可以实现滑动了。因为歌词界面只有文字,所以布局文件中只有一个TextView。

在写完了布局文件之后,我们就要写java文件了,新建一个类LyricsActivity继承自AppCompatActivity,代码如下:

package edu.whut.xucheng.job2;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;

/**
 * Created by dragonhaw on 2016/10/24.
 */

public class LyricsActivity extends AppCompatActivity {
    private String[] lyrics_text = {
                    "穿起一身金衣装\n" +
                    "取消今天的工作\n" +
                    "挤身缤纷的色彩\n" +
                    "来让我去告诉你\n" +
                    "派对永无真意义\n" +
                    "不管相识不相识\n" +
                    "尽管多 D Say Hello\n" +
                    "不需诸多的挑剔\n" +
                    "无谓太过有性格\n" +
                    "派对你要不缺席\n" +
                    "你话唔俾面\n" +
                    "佢话唔赏面\n" +
                    "似为名节做奴隶\n" +
                    "种种方式的捆绑\n" +
                    "请柬一出怎抵挡\n" +
                    "想出千般的推搪\n" +
                    "明日富贵与闭翳\n" +
                    "也要靠你俾下面\n" +
                    "你话唔俾面\n" +
                    "佢话唔赏面\n" +
                    "似为名节做奴隶\n" +
                    "你都咪话唔俾面\n" +
                    "咪话唔赏面\n" +
                    "似用人脸造钱币\n" +
                    "你话唔俾面\n" +
                    "佢话唔赏面\n" +
                    "似为名节做奴隶\n" +
                    "你都咪话唔俾面\n" +
                    "咪话唔赏面\n" +
                    "似用人脸造钱币\n" +
                    "至惊至惊你地唔俾面\n" +
                    "至惊至惊你地唔俾面\n" +
                    "至惊至惊你地唔俾面\n" +
                    "至惊至惊你地唔俾面",
            "拦路雨偏似雪花\n" +
                    "饮泣的你冻吗\n" +
                    "这风褛我给你磨到有襟花\n" +
                    "连调了职也不怕\n" +
                    "富士山下\n" +
                    "富士山下\n" +
                    "怎么始终牵挂\n" +
                    "苦心选中今天想车你回家\n" +
                    "原谅我不再送花\n" +
                    "伤口应要结疤\n" +
                    "花瓣铺满心里坟场才害怕\n" +
                    "如若你非我不嫁\n" +
                    "彼此终必火化\n" +
                    "一生一世等一天需要代价\n" +
                    "谁都只得那双手\n" +
                    "靠拥抱亦难任你拥有\n" +
                    "要拥有必先懂失去怎接受\n" +
                    "曾沿着雪路浪游\n" +
                    "为何为好事泪流\n" +
                    "谁能凭爱意要富士山私有\n" +
                    "何不把悲哀感觉\n" +
                    "假设是来自你虚构\n" +
                    "试管里找不到它染污眼眸\n" +
                    "前尘硬化像石头\n" +
                    "随缘地抛下便逃走\n" +
                    "我绝不罕有\n" +
                    "往街里绕过一周\n" +
                    "我便化乌有\n" +
                    "情人节不要说穿\n" +
                    "只敢抚你发端\n" +
                    "这种姿态可会令你更心酸\n" +
                    "留在汽车里取暖\n" +
                    "应该怎么规劝\n" +
                    "怎么可以将手腕忍痛划损\n" +
                    "人活到几岁算短\n" +
                    "失恋只有更短\n" +
                    "归家需要几里路谁能预算\n" +
                    "忘掉我跟你恩怨\n" +
                    "樱花开了几转\n" +
                    "东京之旅一早比一世遥远\n" +
                    "谁都只得那双手\n" +
                    "靠拥抱亦难任你拥有\n" +
                    "要拥有必先懂失去怎接受\n" +
                    "曾沿着雪路浪游\n" +
                    "为何为好事泪流\n" +
                    "谁能凭爱意要富士山私有\n" +
                    "何不把悲哀感觉\n" +
                    "假设是来自你虚构\n" +
                    "试管里找不到它染污眼眸\n" +
                    "前尘硬化像石头\n" +
                    "随缘地抛下便逃走\n" +
                    "我绝不罕有\n" +
                    "往街里绕过一周\n" +
                    "我便化乌有\n" +
                    "谁都只得那双手\n" +
                    "靠拥抱亦难任你拥有\n" +
                    "要拥有必先懂失去怎接受\n" +
                    "曾沿着雪路浪游\n" +
                    "为何为好事泪流\n" +
                    "谁能凭爱意要富士山私有\n" +
                    "何不把悲哀感觉\n" +
                    "假设是来自你虚构\n" +
                    "试管里找不到它染污眼眸\n" +
                    "前尘硬化像石头\n" +
                    "随缘地抛下便逃走\n" +
                    "我绝不罕有\n" +
                    "往街里绕过一周\n" +
                    "我便化乌有\n" +
                    "你还嫌不够\n" +
                    "我把这陈年风褛\n" +
                    "送赠你解咒",
            "忧郁奔向冷的天 撞落每滴小雨点\n" +
                    "张开口似救生圈 实现雨的酸与甜\n" +
                    "搓起心爱的香烟 弄着脚底的软垫\n" +
                    "酒醉与心碎心碎沟起污染一片\n" +
                    "WOO HOO 无心睡眠 WOO HOO脑交战\n" +
                    "踏着旧日怀念昨天的你\n" +
                    "夜是渗着前事全挥不去\n" +
                    "若是你在明日能得一见\n" +
                    "就让我在怀内重得温暖\n" +
                    "忧郁奔向冷的天\n" +
                    "活在我的心里边\n" +
                    "始终只有你方可\n" +
                    "令逝去的心再甜\n" +
                    "忧郁奔向冷的天 撞落每滴小雨点\n" +
                    "张开口似救生圈 实现雨的酸与甜\n" +
                    "搓起心爱的香烟 弄着脚底的软垫\n" +
                    "酒醉与心碎心碎沟起污染一片\n" +
                    "WOO HOO无心睡眠 WOO HOO脑交战\n" +
                    "踏着旧日怀念昨天的你\n" +
                    "夜是渗着前事全挥不去\n" +
                    "若是你在明日能得一见\n" +
                    "就让我在怀内重得温暖\n" +
                    "忧郁奔向冷的天\n" +
                    "活在我的心里边\n" +
                    "始终只有你方可\n" +
                    "令逝去的心再甜\n" +
                    "WOO HOO无心睡眠 WOO HOO脑交战\n" +
                    "踏着旧日怀念昨天的你\n" +
                    "夜是渗着前事全挥不去\n" +
                    "若是你在明日能得一见\n" +
                    "就让我在怀内重得温暖\n" +
                    "忧郁奔向冷的天 活在我的心里边\n" +
                    "始终只有你方可 令逝去的心再甜\n" +
                    "忧郁奔向冷的天 活在我的心里边\n" +
                    "始终只有你方可 令逝去的心再甜\n" +
                    "忧郁奔向冷的天"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lyrics);
        TextView lyrics = (TextView) findViewById(R.id.lyrics);
        Intent intent = this.getIntent();
        //得到从MainActivity传入的num值,第二个参数0为如果没有数据传入,默认的值就是为0
        int num = intent.getIntExtra("num", );
        lyrics.setText(lyrics_text[num]);

    }
}
           

这里,别忘了在AndroidManifest.xml文件中配置下LyricsActivity。

</activity>
        <activity android:name=".LyricsActivity" >
           

好啦,我们的第二次作业就这样做完了,接下来可以运行看下效果。点开《俾面派对》这首歌,一段摇滚的旋律就出来了,果然是Beyond的风格。再点开《富士山下》,Eason的沙哑的声音就出来了。嘿嘿,好啦,老师想要的结果就做好了。

第二次作业——Service、Listview与ACtivity参数传递源代码点击此处下载

源代码点击此处下载

继续阅读