手機影音第四天,頂部標題欄的布局實現與本地視頻的搜索
前面講了下面的菜單布局與中間的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
手機影音第四天,頂部標題欄的布局實現與本地視頻的搜索