1. 程式人生 > >手機影音第四天,頂部標題欄的布局實現與本地視頻的搜索

手機影音第四天,頂部標題欄的布局實現與本地視頻的搜索

頂部標題欄的布局實現與本地視頻的搜索

前面講了下面的菜單布局與中間的fragmentLayout的布局與實現,今天就寫了頂部title的布局以及去搜索本地sd卡裏的視頻。

一、頂部布局實現

效果圖如下:

技術分享

1、分析下:

a、這個頂部布局是個LinearLayout布局

b、左側這個321影音是個ImageView,然後這個搜索框是一個TextView,右側的遊戲圖標是個相對布局,裏面是一個textview和一個Image構成的點,最右側的那個記錄是一個Imageview

c、最主要的是中間的這個搜索框,為什麽是一個textview呢,這個組件的drawableleft是一個搜索圖標,背景是一個矩形,然後這個textview還可以點擊,就實現了這個搜索框的設計,詳細見代碼。


2、activity_main.xml裏,把頂部的這個布局作為一個外部布局文件,然後引入到這裏。

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

    <!-- 標題欄-->
    <include layout="@layout/activity_titlebar"/>

    <!--frameLayout -->
    <FrameLayout
        android:background="#22000000"
        android:id="@+id/fl_main_content"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="0dp"/>
        .
        .
        .
        .

2、activity_titlebar.xml裏,最外層是一個LinearLayout,這裏顯示的是一個TitleBar,是因為我自定義了一個類,繼承了LinearLayout,這個類實現了標題欄布局裏組件的初始化、點擊事件。

<?xml version="1.0" encoding="utf-8"?>
<com.yuanlp.mobileplayer.view.TitleBar xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="horizontal"
              android:layout_width="match_parent"
              android:background="#ff3097fd"
              android:gravity="center_vertical"
              android:layout_height="55dp">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_topbanner_logo"
        android:layout_marginLeft="8dp"
        />

    <TextView
        android:layout_weight="1"
        android:layout_marginLeft="5dp"
        android:drawablePadding="3dp"
        android:id="@+id/tv_search"
        android:drawableLeft="@drawable/tv_search_drawable_selector"
        android:background="@drawable/tv_search_bg_selector"
        android:textColor="@drawable/ic_tv_search_textcolor_selector"
        android:clickable="true"
        android:textSize="14sp"
        android:text="全網搜索"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <RelativeLayout
        android:id="@+id/rl_game"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_game"
            android:drawableLeft="@drawable/ic_topbanner_game"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <ImageView
            android:layout_alignRight="@+id/tv_game"
            android:background="@drawable/dot"
            android:layout_width="6dp"
            android:layout_height="6dp"/>
    </RelativeLayout>

    <ImageView
        android:id="@+id/iv_record"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="8dp"
        android:background="@drawable/ic_topbanner_record"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</com.yuanlp.mobileplayer.view.TitleBar>

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

<?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">
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
    <TextView
        android:visibility="gone"
        android:textSize="18sp"
        android:textColor="#000000"
        android:id="@+id/tv_nomedia"
        android:text="沒有發現視頻"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <ProgressBar
        android:layout_centerInParent="true"
        android:id="@+id/pb_loading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>


</RelativeLayout>

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<MediaItem> 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卡的數據方法。

本文出自 “YuanGuShi” 博客,請務必保留此出處http://cm0425.blog.51cto.com/10819451/1947740

手機影音第四天,頂部標題欄的布局實現與本地視頻的搜索