前面讲了下面的菜单布局与中间的fragmentLayout的布局与实现,今天就写了顶部title的布局以及去搜索本地sd卡里的视频。

    一、顶部布局实现

        效果图如下:

    1、分析下:

    a、这个顶部布局是个LinearLayout布局

    b、左侧这个321影音是个ImageView,然后这个搜索框是一个TextView,右侧的游戏图标是个相对布局,里面是一个textview和一个Image构成的点,最右侧的那个记录是一个Imageview

   c、最主要的是中间的这个搜索框,为什么是一个textview呢,这个组件的drawableleft是一个搜索图标,背景是一个矩形,然后这个textview还可以点击,就实现了这个搜索框的设计,详细见代码。

2、activity_main.xml里,把顶部的这个布局作为一个外部布局文件,然后引入到这里。

    
    
    
    
        .        .        .        .

2、activity_titlebar.xml里,最外层是一个LinearLayout,这里显示的是一个TitleBar,是因为我自定义了一个类,继承了LinearLayout,这个类实现了标题栏布局里组件的初始化、点击事件。

    
    
    
        
        
        

3、TitleBar 用于对title布局里组件的实例化与点击事件

package com.yuanlp.mobileplayer.view;import android.content.Context;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;import android.widget.LinearLayout;import android.widget.Toast;import com.yuanlp.mobileplayer.R;/** * Created by 原立鹏 on 2017/7/14. * 自定义标题栏类 */public class TitleBar extends LinearLayout implements View.OnClickListener {    private View tv_search;  //输入框的ID对应的控件    private View rl_ganme;    private View iv_record;    private Context context;    /**     * 在代码中实例化该类的时候,使用     * @param context     */    public TitleBar(Context context) {        this(context,null);    }    /**     * 在布局文件使用时,Android系统通过这个构造方法实例化该类     * @param context     * @param attrs     */    public TitleBar(Context context, @Nullable AttributeSet attrs) {        this(context, attrs,0);    }    /**     * 当需要设置样式的时候,可以使用该方法     * @param context     * @param attrs     * @param defStyleAttr     */    public TitleBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        this.context=context;    }    /**     * 当布局文件加载完成后,回调这个方法     */    @Override    protected void onFinishInflate() {        super.onFinishInflate();        //得到子控件实例        tv_search=getChildAt(1);        rl_ganme=getChildAt(2);        iv_record=getChildAt(3);        //设置点击事件        tv_search.setOnClickListener(this);        rl_ganme.setOnClickListener(this);        iv_record.setOnClickListener(this);    }    /**     * Called when a view has been clicked.     *     * @param v The view that was clicked.     */    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.tv_search:                Toast.makeText(context,"点击了搜索",Toast.LENGTH_SHORT).show();                break;            case R.id.rl_game:                Toast.makeText(context,"点击了游戏",Toast.LENGTH_SHORT).show();                break;            case R.id.iv_record:                Toast.makeText(context,"点击了播放历史",Toast.LENGTH_SHORT).show();                break;        }    }}

至此,整个主界面的布局完成,后面的就是完善细节。

二、搜索本地视频

    搜索本地视频,有2种办法:

    第一种是笨方法,检索SD卡里后缀名,获取视频,

    第二种:Android系统会在SD卡插拔后,自动通过Media provder来检索视频,然后存储,然后通过ContentProvder来对外公布这些视频信息。

    在这里主要使用第二种办法。

1、定义展现视频列表的布局,在这里通过listview来展现视频列表,有一个progressbar,在加载数据时显示,加载完成后隐藏;一个textview,当没有视频时,显示提示信息,有视频时,不显示。

    activity_pager.xml

    
    
    

    2、重写VideoPager

        在初始化该类时,加载上面的这个布局,并实例化各个组件,然后在初始化数据时,去获取SD卡数据。这里加载数据,要在子线程中去写,不能卸载UI线程中,防止出现ANR错误。通过Handler来实现。

    

package com.yuanlp.mobileplayer.pager;import android.content.ContentResolver;import android.content.Context;import android.database.Cursor;import android.net.Uri;import android.os.Handler;import android.os.Message;import android.provider.MediaStore;import android.view.View;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.TextView;import com.yuanlp.mobileplayer.R;import com.yuanlp.mobileplayer.base.BasePager;import com.yuanlp.mobileplayer.bean.MediaItem;import com.yuanlp.mobileplayer.utils.LogUtil;import java.util.ArrayList;import java.util.List;/** * Created by 原立鹏 on 2017/7/13. * 本地视频的页面 */public class VideoPager extends BasePager {    private ListView listview;    private TextView nomedia;    private ProgressBar pb_loding;    //保存所有的媒体信息的集合    private List
 mediaList;    public VideoPager(Context context) {        super(context);    }    private Handler handler=new Handler(){        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            if (mediaList!=null&&mediaList.size()>0){                //有数据                //设置适配器            }else{                //没有数据                //文本显示            }            //progressbar隐藏        }    };    /**     * 强制子类实现特定的效果     *     * @return     */    @Override    public View initView() {        LogUtil.e("本地视频被初始化了");       View view=View.inflate(context, R.layout.video_pager,null);        listview= (ListView) view.findViewById(R.id.listview);        nomedia= (TextView) view.findViewById(R.id.tv_nomedia);        pb_loding= (ProgressBar) view.findViewById(R.id.pb_loading);        return view;    }    @Override    public void initData() {        super.initData();        LogUtil.e("本地视频页面的数据被初始化了");        //加载本地数据        getDataFromLocal();    }    /**     * 从本地sd卡获取数据,有2中办法     * 1、遍历sd卡,根据后缀名     * 2、从内容提供者中获取,系统有自己会去扫描所有media信息。     * 3/6.0后的系统,需要加上动态权限     */    private void getDataFromLocal() {        mediaList=new ArrayList<>();        new Thread(){            @Override            public void run() {                super.run();                //根据上下文,去获取内容解析者                ContentResolver resolver = context.getContentResolver();                Uri uri= MediaStore.Video.Media.EXTERNAL_CONTENT_URI;                String[] objs={                       MediaStore.Video.Media.DISPLAY_NAME, //视频文件名称                        MediaStore.Video.Media.DURATION,  //视频时长                        MediaStore.Video.Media.SIZE, //文件大小                        MediaStore.Video.Media.DATA, //视频的绝对地址                        MediaStore.Video.Media.ARTIST,  //歌曲的演唱者,艺术家(音频可能会有该字段)                };                Cursor cursor = resolver.query(uri, objs, null, null, null);                if (cursor!=null){                    while(cursor.moveToNext()){                        MediaItem item=new MediaItem();                        String name=cursor.getString(0); //名称                        item.setName(name);                        long duration=cursor.getLong(1); //时长                        item.setDuration(duration);                        long size=cursor.getLong(2); //视频大小                        item.setSize(size);                        String data=cursor.getString(3); //视频的绝对地址                        item.setData(data);                        String artist=cursor.getString(4); //艺术家                        item.setArtist(artist);                        mediaList.add(item); //把每个item数据放到集合中                    }                    cursor.close();                }                //发消息,提示加载完media                handler.sendEmptyMessage(0);            }        }.start();    }}

3、音视频的实体类,MediItem,主要是音视频的一些属性形成的类

package com.yuanlp.mobileplayer.bean;/** * Created by 原立鹏 on 2017/7/14. * 代表一个视频和音频 */public class MediaItem {    private String name;    private long duration;    private long size;    private String data;    private String artist;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public long getDuration() {        return duration;    }    public void setDuration(long duration) {        this.duration = duration;    }    public long getSize() {        return size;    }    public void setSize(long size) {        this.size = size;    }    public String getData() {        return data;    }    public void setData(String data) {        this.data = data;    }    public String getArtist() {        return artist;    }    public void setArtist(String artist) {        this.artist = artist;    }    @Override    public String toString() {        return "MediaItem{" +                "name='" + name + '\'' +                ", duration=" + duration +                ", size=" + size +                ", data='" + data + '\'' +                ", artist='" + artist + '\'' +                '}';    }}

今天主要的地方就是在于标题栏布局中的搜索框那里,还有就是获取本地SD卡的数据方法。