Android端本地音樂播放器(二)---應用主界面的實現

前言介紹見Android音樂播放器(一)—前言
DisplayActivity設計見圖1,實際效果見圖2。圖1的左側是DisplayActivity佈局文件的層次結構。

圖1

width = 600

圖2

在這裏插入圖片描述

1.設置主題style.xml

想要使用toolbar首先需要將actionbar置空,在styles.xml中設置AppTheme的parent爲xxxx.NoActionBar。
AppTheme默認在manifest文件中被使用爲application的android:theme屬性。

2.toolbar控件添加

在DisplayActivity的佈局文件中的合適的位置添加toolbar控件。

android:layout_height="?attr/actionBarSize"是設置高度爲系統默認的actionbar的高度,爲56dp。

app:navigationIcon是工具欄最左側的圖標,後續可以在代碼中實現該圖標的點擊事件,比如將它設置爲返回按鈕,在本應用的主界面這裏,設置的是一個菜單圖標,點擊後顯示側邊欄菜單。

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_activity_display"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:navigationIcon="@drawable/menu_gray"
    android:background="@color/black_color"
    app:title="@string/title_toolbar"
    app:titleTextColor="@color/white_color" />

在activity的onCreate()方法中加載該控件:

Toolbar toolbar = findViewById(R.id.toolbar_activity_display);
setSupportActionBar(toolbar);

3.配合DrawerLayout實現側邊欄

在DisplayActivity的最外層的佈局是DrawerLayout,裏面有兩個LinearLayout佈局,第一個是DisplayActivity的正常內容的佈局,第二個是側邊欄的佈局。

側邊欄的初始化在onCreate()方法中調用config_DrawerLayout()方法(自己是實現的方法),代碼如下。
此方法中會用到兩個全局變量,一個是側邊欄控件本身,另一個是用於將側邊欄、toolbar進行聯繫起來、配置側邊欄相關動作事件的類的對象。

private DrawerLayout drawerlayout = null;//側滑欄
private ActionBarDrawerToggle drawerToggle = null;
public void config_DrawerLayout() {
        drawerlayout = findViewById(R.id.drawer_layout);
        /*後面兩個參數是@StringRes int openDrawerContentDescRes, @StringRes int         
        closeDrawerContentDescRes根據我看完源碼猜測爲側邊欄打開和關閉時的描述文本信息*/
        drawerToggle = new ActionBarDrawerToggle(this, drawerlayout, toolbar, R.string.app_name, R.string.app_name) {
            @Override
            public void onDrawerOpened(View drawerView) {//完全打開時觸發
                super.onDrawerOpened(drawerView);
                //Toast.makeText(DisplayActivity.this,"onDrawerOpened",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onDrawerClosed(View drawerView) {//完全關閉時觸發
                super.onDrawerClosed(drawerView);
                //Toast.makeText(DisplayActivity.this,"onDrawerClosed",Toast.LENGTH_SHORT).show();
            }

            /**
             * 當抽屜被滑動的時候調用此方法
             * slideOffset表示 滑動的幅度(0-1)
             */
            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
            }

            /**
             * 當抽屜滑動狀態改變的時候被調用
             * 狀態值是STATE_IDLE(閒置--0), STATE_DRAGGING(拖拽的--1), STATE_SETTLING(固定--2)中之一。
             *具體狀態可以慢慢調試
             */
            @Override
            public void onDrawerStateChanged(int newState) {
                super.onDrawerStateChanged(newState);
            }
        };
        drawerlayout.setDrawerListener(drawerToggle);
        //設置toolbar左側圖標點擊打開側滑欄
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (drawerlayout.isDrawerOpen(GravityCompat.START)) {
                    //Log.w("DisplayActivity", "closeDrawer");
                    drawerlayout.closeDrawer(GravityCompat.START);
                } else {
                    //Log.w("DisplayActivity", "openDrawer");
                    drawerlayout.openDrawer(GravityCompat.START);
                }
            }
        });
        //配置側滑界面listView
        List<DrawerLayoutListViewItem> drawer_list_view_content = new ArrayList<>();
        DrawerLayoutListViewItem myLoveSongs = new DrawerLayoutListViewItem(R.drawable.love, "我喜歡的音樂");
        DrawerLayoutListViewItem stopWithTime = new DrawerLayoutListViewItem(R.drawable.stop_with_time, "定時停止播放");
        DrawerLayoutListViewItem play_mode_select = new DrawerLayoutListViewItem(R.drawable.setting, "播放模式");
        DrawerLayoutListViewItem feedback_suggestions = new DrawerLayoutListViewItem(R.drawable.about, "關於");
        DrawerLayoutListViewItem exit = new DrawerLayoutListViewItem(R.drawable.exit_2, "退出");
        drawer_list_view_content.add(myLoveSongs);
        drawer_list_view_content.add(play_mode_select);
        drawer_list_view_content.add(stopWithTime);
        drawer_list_view_content.add(feedback_suggestions);
        drawer_list_view_content.add(exit);
        DrawerLayoutListViewAdapter drawer_list_view_adapter = new DrawerLayoutListViewAdapter(DisplayActivity.this, R.layout.drawer_layout_list_item, drawer_list_view_content);
        drawer_layout_list_view.setAdapter(drawer_list_view_adapter);
    }

DrawerLayoutListViewItem類是一個JAVA Bean類,用於存儲側邊欄的listview的每個item,具體代碼如下,包含一張圖片和一個字符串。

/**側滑欄ListView的item*/
public class DrawerLayoutListViewItem {
    private int item_picture;//item圖片
    private String item_title;//item標題
    public DrawerLayoutListViewItem(int item_picture, String item_title) {
        this.item_picture = item_picture;
        this.item_title = item_title;
    }
    public int getItem_picture() {
        return item_picture;
    }
    public void setItem_picture(int item_picture) {
        this.item_picture = item_picture;
    }
    public String getItem_title() {
        return item_title;
    }
    public void setItem_title(String item_title) {
        this.item_title = item_title;
    }
}

DrawerLayoutListViewAdapter類是用於將ArrayList中的數據適配到listview的每個item裏面去的。
每次有子項滑動到屏幕內時就會調用getView方法。爲了充分利用緩存,會首先判斷convertView是否爲空,不爲空的話就直接複用,往view的控件裏面裝載數據即可;如果爲空的話就需要重新加載控件並存儲到viewholder裏面。

package edu.whut.ruansong.musicplayer.tool;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

import edu.whut.ruansong.musicplayer.R;
import edu.whut.ruansong.musicplayer.model.DrawerLayoutListViewItem;

public class DrawerLayoutListViewAdapter extends ArrayAdapter<DrawerLayoutListViewItem> {
    private int resourceId;//用來放置佈局文件的id
    //適配器的構造函數
    public DrawerLayoutListViewAdapter(Context context, int textViewResourceId, List<DrawerLayoutListViewItem> objects) {
        super(context, textViewResourceId, objects);
        resourceId = textViewResourceId;
    }
    class ViewHolder {

        ImageView itemImage;

        TextView itemTitle;

    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        DrawerLayoutListViewItem item = getItem(position); // 獲取當前項的item實例
        View view;//子項佈局對象
        ViewHolder viewHolder;//內部類對象
        if(convertView == null){//第一次加載
            view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
            viewHolder = new ViewHolder();
            viewHolder.itemImage = view.findViewById(R.id.drawer_layout_list_item_image);
            viewHolder.itemTitle = view.findViewById(R.id.drawer_layout_list_item_title);
        }else{//不是第一次,即佈局文件已經加載,可以利用
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }
        if(item != null && viewHolder!= null){
            viewHolder.itemImage.setImageResource(item.getItem_picture());
            viewHolder.itemTitle.setText(item.getItem_title());
        }
        return view;
    }
}

側邊欄效果如圖3:

圖3

在這裏插入圖片描述

4.搜索圖標的實現

搜索圖標不是在佈局文件中寫出來的,是通過menu文件配合代碼實現的。
在res目錄下新建menu文件夾,新建xml文件,命名爲menu_xxxxx.xml(這裏我命名爲menu_display.xml)。
app:showAsAction="always"表示toolbar有沒有空間都會要求顯示搜索圖標。
item標籤是可以多實現幾個的,多了以後可能會出現豎狀的3個點,點擊以後會出現詳細的選項。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
    android:id="@+id/display_toolbar_menu_search"
    android:title="@string/search"
    android:icon="@drawable/search"
    app:showAsAction="always"/>
</menu>

然後在DisplayActivity(主界面activity)中重寫父類的兩個方法,代碼如下:

/**
     * toolbar的menu加載
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_display, menu);
        return true;
    }

    /**
     * toolbar的menu點擊事件
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.display_toolbar_menu_search://toolbar上的搜索按鈕
                Intent intent_jump_toolbar_search =
                        new Intent(DisplayActivity.this, SearchDetailActivity.class);
                startActivity(intent_jump_toolbar_search);
                break;
            default:
                break;
        }
        return true;
    }

這裏搜索圖標的點擊事件是跳轉到搜索界面(SearchDetailActivity)去。

5.歷史播放記錄控件的實現

歷史播放記錄控件是一個單獨的佈局文件實現的。用垂直的線性佈局包含了一個文本框和一個listview控件,背景採用圓角卡片式效果。
然後在DisplayActivity的佈局文件中採用include的方式引入歷史播放記錄控件。

 <include layout="@layout/my_history_view"
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	android:layout_margin="@dimen/dp_10"
	android:layout_above="@+id/play_bar_bottom"/>

圓角卡片式的實現採用新建xml文件,寫shape標籤的形式來實現,具體代碼如下。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <!-- 描邊 -->
    <stroke
        android:width="1dp"
        android:color="@color/black_color" />
    <!-- 漸變 -->
    <gradient
        android:startColor="#D5CFCF"
        android:endColor="#D5CFCF"/>
    <!-- 圓角角度 -->
    <corners
        android:radius="10dp" />
</shape>

6.播放進度條

採用ProgressBa控件實現,在後臺服務service中定時向主界面發送廣播更新進度條的進度。
style設置進度條爲水平方向,可選垂直方向
在styles.xml文件中colorAccent定義了進度條的默認顏色,如下語句:

@color/colorAccent

<ProgressBar
	android:id="@+id/progressBar_activity_display"
	android:layout_width="match_parent"
	android:layout_height="5dp"
	android:layout_above="@+id/play_bar_bottom"
	android:max="100"
	android:progress="0"
	style="@style/Widget.AppCompat.ProgressBar.Horizontal"
	android:background="@color/gray_color"/>

7.底部播放狀態控制條

具體實現可以參閱代碼activity_display.xml,只是單純的控件的堆疊。

以上是主界面的界面的實現,下一篇計劃分析本應用的播放邏輯的控制方法。
求贊,謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章