基于android的网络音乐播放器-下载完成后下拉音乐列表刷新(八)

作为android初学者,最近把疯狂android讲义和疯狂Java讲义看了一遍,看到书中介绍的知识点非常多,很难全部记住,为了更好的掌握基础知识点,我将开发一个网络音乐播放器-EasyMusic来巩固下,也当作是练练手。感兴趣的朋友可以看看,有设计不足的地方也欢迎指出。

开发之前首先介绍下该音乐播放器将要开发的功能(需求):

1.本地音乐的加载和播放;

2.网络音乐的搜索,试听和下载;

3.音乐的断点下载;

4.点击播放图标加载专辑图片,点击歌词加载歌词并滚动显示(支持滑动歌词改变音乐播放进度);

5.支持基于popupWindow的弹出式菜单;

6.支持后台任务栏显示和控制。

该篇主要是介绍下载歌曲完成后下拉音乐列表进行刷新,这样新下载的音乐将会添加到列表中来。
在上节中介绍下载时代码中有提到过将已下载完成的歌曲扫描进媒体库的方法scanFileToMedia(targetFile);该方法的具体代码如下

public class DownloadUtil {
    public void scanFileToMedia(final String url) {
        new Thread(new Runnable() {
            public void run() {
                MediaScannerConnection.scanFile(mContext, new String[] {url}, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            Log.d(TAG, "scan completed : file = " + url);
                        }
                    });
            }

        }).start();
    }
}

将音乐文件扫描进媒体库后重新从媒体库中获取音乐数据就可以获得最近下载的歌曲从而更新了音乐列表(添加音乐)。

通过上面我们知道,媒体库扫描进音乐文件后我们在音乐列表中下拉列表实现刷新(实际是重新获取媒体库中的音乐文件),支持下拉的音乐列表需要我们重写listview,当然给listView添加处理OnTouchEvent的方法也是可以实现一样的效果的,但是重写的支持下拉刷新的listview内部封装了各个细节操作,其他项目需要的时候也可以直接使用该类–自定义view都有这种好处。

下面是重写listview的代码,注释已经写的很清楚了,相信看懂不难。

package com.sprd.easymusic.myview;

import com.sprd.easymusic.R;
import com.sprd.easymusic.fragment.MusicListFragment;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;
import android.view.View.OnTouchListener;

public class RefreshableListView extends ListView implements OnScrollListener, OnTouchListener {
    private static final String TAG = "RefreshableListView";
    private LayoutInflater inflater;
    //listview需要添加的headeriew
    private LinearLayout header;
    private RelativeLayout headerView;
    //下拉刷新等提示语
    private TextView refreshText;
    //指示箭头和进度条
    private ImageView arrow;
    private ProgressBar bar;
    //触摸点坐标-下拉起始点
    private int temY = 0;
    //下拉的间距
    private int detY = 0;
    private int headerHeight;
    //是否正在刷新
    private boolean isRefreshing;
    //当前状态是否支持刷新动作,listview到顶部了才支持刷新
    private boolean canRefresh = false;
    private Handler handler;
    private Handler refreshHandler;
    private static final int REFRESH_COMPLETE = 1;
    private static final int REFRESH_FINISH = 2;

    public RefreshableListView(Context context) {
        super(context);
        initHeaderView(context);
    }

    //必须实现的方法,否则xml文件解析出错
    public RefreshableListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initHeaderView(context);
    }

    //添加头视图的方法
    private void initHeaderView(final Context context) {
        inflater = LayoutInflater.from(context);
        header = (LinearLayout)inflater.inflate(R.layout.header_view, this, false);
        headerView = (RelativeLayout) header.findViewById(R.id.header_view);
        setHeaderViewHeight();
        refreshText = (TextView) header.findViewById(R.id.refreshText);
        refreshText.setText("下拉可以刷新");
        bar = (ProgressBar) header.findViewById(R.id.progressBar1);
        bar.setVisibility(View.GONE);
        arrow = (ImageView) header.findViewById(R.id.arrow);
        headerView.setVisibility(View.GONE);
        this.addHeaderView(header);
        this.setOnTouchListener(this);
        this.setOnScrollListener(this);
        //刷新过程更新UI的handler
        handler = new Handler() {
            public void handleMessage(Message msg) {
                switch(msg.what) {
                case REFRESH_COMPLETE:
                    bar.setVisibility(View.INVISIBLE);
                    refreshText.setText("刷新成功");
                    //Toast.makeText(context, "刷新成功", 300).show();
                    sendMessageDelayed(handler.obtainMessage(REFRESH_FINISH), 300);
                    break;
                case REFRESH_FINISH:
                    isRefreshing = false;
                    headerView.setVisibility(View.GONE);
                    arrow.setVisibility(View.VISIBLE);
                    bar.setVisibility(View.GONE);
                    refreshText.setText("下拉可以刷新");
                    break;
                default:
                    break;
                }
            }

        };
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        Log.d(TAG, "onScrollStateChanged: scrollState = " + scrollState);
    }

    //监听当前列表状态
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        Log.d(TAG, "onScroll"); 
        //更具列表状态判断当前是否支持刷新,若第0个item不可见-即列表没有到达顶部的状态是不支持刷新的
        if (firstVisibleItem == 0) {
            canRefresh = true;
        } else {
            canRefresh = false;
        }
    }

    //下拉刷新的动作处理
    public boolean onTouch(View v, MotionEvent event) {
        if (isRefreshing || !canRefresh) return false;
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            temY = (int)event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            detY = (int)event.getY() - temY;
            detY = detY > 600 ? 600 : detY;
            applyChange();
            break;
        case MotionEvent.ACTION_UP:
            checkIfNeedRefresh();
            detY = 0;
            temY = 0;
            break;
        }
        return false;
    }

    //判断下拉的间距是否足够刷新
    private void checkIfNeedRefresh() {
        header.setPadding(0, 0, 0, 0);
        if (detY > 200) {
            startRefreshing();
        } else {
            headerView.setVisibility(View.GONE);
            refreshText.setText("下拉可以刷新");
        }
    }

    //开始刷新,更新UI
    private void startRefreshing() {
        arrow.setVisibility(View.GONE);
        bar.setVisibility(View.VISIBLE);
        refreshText.setText("正在刷新");
        isRefreshing = true;
        refreshMusic();
    }

    //刷新完成,更新UI
    public void refreshComplete() {
        handler.sendMessage(handler.obtainMessage(REFRESH_COMPLETE));
    }

    //通知handler刷新列表,更新UI
    private void refreshMusic() {
        if (refreshHandler != null) {
            refreshHandler.sendMessage(refreshHandler.obtainMessage(MusicListFragment.REFERSH_MUSIC));
        }
    }

    //随着下拉间距的增大,显示内容随之改变
    private void applyChange() {
        //this.setY(-headerHeight + detY);
        if (detY <= 20) return;
        //header.setY(-headerHeight + detY/3);
        Log.d(TAG, "detY = " + detY);
        arrow.setVisibility(View.VISIBLE);
        headerView.setVisibility(View.VISIBLE);
        header.setPadding(0, detY/3, 0, 0);
        if (detY > 200) {
            refreshText.setText("释放立即刷新");
            arrow.setImageResource(R.drawable.refresh2);
        } else {
            refreshText.setText("下拉可以刷新");
            arrow.setImageResource(R.drawable.refresh1);
        }
    }

    public void setHandler(Handler refreshHandler) {
        this.refreshHandler = refreshHandler;
    }

    public boolean isRefreshing() {
        return isRefreshing;
    }

    //获取listview头视图的高度
    public void setHeaderViewHeight() {
        header.measure(0, 0);
        headerHeight = header.getMeasuredHeight();
        Log.d(TAG, "headerHeight = " + headerHeight + "position-y = " + header.getY());
    }

}

音乐播放器已完成,下载地址:
Android音乐播放器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值