本来想给大家讲解一个饭否的开源项目,结果发现公司网端被封,模拟器是无法跳过防火墙上网的,设置了AVD的DNS也不行,没办法只能转向无internet连接的项目讲解,正好昨天论坛上有一个人问我关于音乐播放器的问题,那这次就一个常用的音乐播放项目作为讲解内容,多的不说还是先上图:
对于音乐播放器的框架我就不说了,因为项目不是很大,但是也不小,所以今天我先介绍下主界面的UI设计,我们先看主界面看感觉很简单一个listview显示歌曲,listview下面有个按钮,点击以后会想上滑动出歌曲的详细界面,这里和开源的sildemenu很像,不过sildemenu现在只能水平方向滑动,其实这里是实现抽屉效果,自定义SlidingDrawer,好的,今天就介绍如何实现SlidingDrawer的UI设计。
首先主界面的xml如下:
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background">
这里是设置背景图片
<RelativeLayout
android:id="@+id/ListLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="4dp"
android:layout_marginBottom="42dp"
android:background="@drawable/listlayout_bg">
<ListView
android:id="@+id/listView"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_marginTop="60dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:cacheColorHint="#00000000"
android:divider="@color/divider_color"
android:dividerHeight="1dp"
android:scrollbars="none"
android:listSelector="@drawable/selector_list_item">
</ListView>
这里是设置音乐的listview
<View
android:background="@drawable/shape_line"
android:layout_marginTop="60dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_width="fill_parent"
android:layout_height="1dp" />
最上方button和listview中间的白线
<RelativeLayout
android:id="@+id/ListTitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="60dp"
android:layout_alignParentTop="true"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Aimn音乐库"
android:textColor="#666666"
android:textSize="20dp"
android:background="@drawable/prompt">
</Button>
这里设置最上方的button
</RelativeLayout>
</RelativeLayout>
<com.genius.widget.MySlidingDrawer
android:id="@+id/slidingDrawer"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:handle="@+id/handle"
android:content="@+id/content"
android:topOffset="10dp">
<includelayout="@layout/sliderdrawer_handle_layout"></include>
<includelayout="@layout/sliderdrawer_content_layout"></include>
</com.genius.widget.MySlidingDrawer>
这里就是最关键的自定义SlidingDrawer的加载。
<RelativeLayout
android:id="@+id/VirtualLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#60000000"
android:visibility="invisible">
</RelativeLayout>
</RelativeLayout>
这里可以看到两个include layout,分别绑定id为handle和content,这两个layout是什么了,首先我们来看名为handle的layout,xml如下:
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/handle"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<ImageButton
android:id="@+id/handler_icon"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/selector_handle_bar"
android:src="@drawable/handle_up">
</ImageButton>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/handlelayout_bg">
<ImageButton
android:id="@+id/cutlineleft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/cut_line"
android:layout_marginLeft="50dp"
android:layout_alignParentLeft="true">
</ImageButton>
<RelativeLayout
android:id="@+id/handle_panel"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageButton
android:id="@+id/handler_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/handle_play_normal"
android:layout_alignParentLeft="true"
android:layout_marginLeft="5dp"
android:layout_centerVertical="true"
android:visibility="invisible">
</ImageButton>
<ImageButton
android:id="@+id/handler_pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/handle_pause_normal"
android:layout_alignParentLeft="true"
android:layout_marginLeft="5dp"
android:layout_centerVertical="true"
android:visibility="invisible">
</ImageButton>
</RelativeLayout>
<ImageButton
android:id="@+id/cutlineright"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/cut_line"
android:layout_marginRight="50dp"
android:layout_alignParentRight="true">
</ImageButton>
<TextView
android:id="@+id/textSongNum"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:text="0/0"
android:color="#999999"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:gravity="center"
android:textStyle="bold"
android:singleLine="true"
></TextView>
<TextView
android:id="@+id/textPlaySong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/default_title_name"
android:color="#999999"
android:layout_centerInParent="true"
android:layout_marginLeft="60dp"
android:layout_marginRight="60dp"
android:ellipsize="marquee"
android:textStyle="bold"
android:textSize="18sp"
android:singleLine="true"
android:focusable="true"
android:focusableInTouchMode="true"></TextView>
</RelativeLayout>
</LinearLayout>
这里有很多控件,但是其实很简单,只是为了实现下图红色框的功能:
那content的layout就不用我细说了,是实现抽屉拉出的那个界面,具体xml:
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/slidercontent_bg">
<RelativeLayout
android:id="@+id/setlayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
<ImageButton
android:id="@+id/buttonMode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/mode_list_loop"
android:background="@drawable/selector_mode_set"
android:layout_alignParentLeft="true">
</ImageButton>
<ImageButton
android:id="@+id/buttonVolumn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/voice"
android:background="@drawable/selector_volum_set"
android:layout_alignParentRight="true">
</ImageButton>
</RelativeLayout>
<com.genius.widget.GalleryFlow
android:id="@+id/imageGallery1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
</com.genius.widget.GalleryFlow>
<com.genius.widget.GalleryFlow
android:id="@+id/imageGallery2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
</com.genius.widget.GalleryFlow>
<RelativeLayout
android:id="@+id/miniplayLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/playcontrol_bg"
android:layout_alignParentBottom="true"
android:gravity="center">
<ImageButton
android:id="@+id/buttonStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_weight="1"
android:src="@drawable/player_stop"
android:background="@drawable/selector_music_btn">
</ImageButton>
<ImageButton
android:id="@+id/buttonMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_weight="1"
android:src="@drawable/menu"
android:background="@drawable/selector_music_btn">
</ImageButton>
<ImageButton
android:id="@+id/buttonPlayPre"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/buttonStop"
android:layout_centerVertical="true"
android:src="@drawable/player_pre"
android:background="@drawable/selector_music_btn">
</ImageButton>
<ImageButton
android:id="@+id/buttonPlayNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/buttonMenu"
android:layout_centerVertical="true"
android:layout_weight="1"
android:src="@drawable/player_next"
android:background="@drawable/selector_music_btn">
</ImageButton>
<ImageButton
android:id="@+id/buttonPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerVertical="true"
android:layout_weight="1"
android:src="@drawable/player_play"
android:background="@drawable/selector_music_btn">
</ImageButton>
<ImageButton
android:id="@+id/buttonPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_weight="1"
android:src="@drawable/player_pause"
android:background="@drawable/selector_music_btn"
android:visibility="invisible">
</ImageButton>
</RelativeLayout>
<RelativeLayout
android:id="@+id/progressLayout"
android:layout_above="@id/miniplayLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:background="@drawable/progresslayout_bg">
<TextView
android:text="00:00"
android:id="@+id/textViewCurTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:textColor="@android:color/white"
android:textStyle="bold"
android:layout_alignParentLeft="true">
</TextView>
<TextView
android:text="00:00"
android:id="@+id/textViewTotalTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:textColor="@android:color/white"
android:textStyle="bold"
android:layout_alignParentRight="true">
</TextView>
<SeekBar
android:id="@+id/seekBar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/textViewCurTime"
android:layout_toLeftOf="@id/textViewTotalTime"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:max="100"
android:progressDrawable="@drawable/seekbar_style"
android:thumb="@drawable/seekbar_thumb"
android:background="@drawable/progress_buffering">
</SeekBar>
</RelativeLayout>
</RelativeLayout>
可视化布局文件其实如下图:
布局写好了,我们就该来自定义这个SlidingDrawer,首先我们需要去官网上看看SlidingDrawer的API,里面有很多方法,我就不细说了,因为我也不懂,哈哈,但是我们重点要知道这个方法onInterceptTouchEvent的方法,ontouch拦截器,为什么要知道这个ontcouh拦截器,因为一会我们要把抽屉的拉出,缩回效果写在里面,为什么写在
onInterceptTouchEvent而不写在ontouch里面,这里我就不细说了,大家可以百度一下他们之间的关系。要怎么写了,抽屉效果其实就是把下面控件往上拉,上面的控件被挤出去的思路,或者反之,所以这里我们首先要获取控件位置,然后计算出新的位置,让相应控件显示到新的位置,由此刷新UI界面。代码如下:
public class MySlidingDrawerextends SlidingDrawer{
private int mHandleId = 0; //抽屉行为控件ID
private int[] mTouchableIds = null; //Handle部分其他控件ID
private IOnSliderHandleViewClickListenermTouchViewClickListener;
public int[] getTouchableIds() {
return mTouchableIds;
}
public void setTouchableIds(int[]mTouchableIds) {
this.mTouchableIds = mTouchableIds;
}
public int getHandleId() {
return mHandleId;
}
public void setHandleId(int mHandleId) {
this.mHandleId = mHandleId;
}
public voidsetOnSliderHandleViewClickListener(IOnSliderHandleViewClickListener listener)
{
mTouchViewClickListener= listener;
}
public MySlidingDrawer(Context context,AttributeSet attrs) {
super(context, attrs);
}
public MySlidingDrawer(Context context,AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
}
/*
* 获取控件的屏幕区域
*/
public Rect getRectOnScreen(View view){
Rect rect = new Rect();
int[] location = new int[2];
View parent = view;
if(view.getParent() instanceof View){
parent = (View)view.getParent();
}
parent.getLocationOnScreen(location);
view.getHitRect(rect);
rect.offset(location[0], location[1]);
return rect;
}
public booleanonInterceptTouchEvent(MotionEvent event) {
// 触摸位置转换为屏幕坐标
int[] location = new int[2];
int x = (int)event.getX();
int y = (int)event.getY();
this.getLocationOnScreen(location);
x += location[0];
y += location[1];
if(mTouchableIds != null){
for(int id :mTouchableIds){
View view =findViewById(id);
if (view.isShown())
{
Rect rect =getRectOnScreen(view);
if(rect.contains(x,y)){
if (event.getAction() ==MotionEvent.ACTION_DOWN)
{
if(mTouchViewClickListener != null)
{
mTouchViewClickListener.onViewClick(view);
}
}
return true;
}
}
}
}
//抽屉行为控件
if(event.getAction() ==MotionEvent.ACTION_DOWN && mHandleId != 0){
View view =findViewById(mHandleId);
Rect rect = getRectOnScreen(view);
if(rect.contains(x, y)){//点击抽屉控件时交由系统处理
{
returnsuper.onInterceptTouchEvent(event);
}
}else{
return false;
}
}
returnsuper.onInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEventevent) {
return super.onTouchEvent(event);
}
}
今天就先说到这儿,重点是让大家了解抽屉效果SlidingDrawer的自定义和这个音乐播放器的UI设计,关于如何用我们这个自定义的SlidingDrawer,下章内容会详细介绍。关于源码,会在该音乐播放器的最后一节上上传。