???????
當然除了使用drawable這樣的圖片外今天談下自定義圖形shape的方法,對于button控件android上支持以下幾種屬性shape、gradient、stroke、corners等。
我們就以目前系統的button的selector為例說下:
<shape>
<gradient
android:startcolor="#ff8c00"
android:endcolor="#ffffff"
android:angle="270" />
<stroke
android:width="2dp"
android:color="#dcdcdc" />
<corners
android:radius="2dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
?
對于上面,這條shape的定義,分別為漸變,在gradient中startcolor屬性為開始的顏色,endcolor為漸變結束的顏色,下面的angle是角度。接下來是stroke可以理解為邊緣,corners為拐角這里radius屬性為半徑,最后是相對位置屬性padding。
對于一個button完整的定義可以為:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://www.norkoo.com">
<item android:state_pressed="true" >
<shape>
<gradient
android:startcolor="#ff8c00"
android:endcolor="#ffffff"
android:angle="270" />
<stroke
android:width="2dp"
android:color="#dcdcdc" />
<corners
android:radius="2dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
<item android:state_focused="true" >
<shape>
<gradient
android:startcolor="#ffc2b7"
android:endcolor="#ffc2b7"
android:angle="270" />
<stroke
android:width="2dp"
android:color="#dcdcdc" />
<corners
android:radius="2dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
<item>
<shape>
<gradient
android:startcolor="#ff9d77"
android:endcolor="#ff9d77"
android:angle="270" />
<stroke
android:width="2dp"
android:color="#fad3cf" />
<corners
android:radius="2dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
</item>
</selector>
?
注意!提示大家,以上幾個item的區別主要是體現在state_pressed按下或state_focused獲得焦點時,當當來判斷顯示什么類型,而沒有state_xxx屬性的item可以看作是常規狀態下。
?
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:color="hex_color"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_active=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_window_focused=["true" | "false"] />
</selector>
?
elements:
<selector>
必須。必須是根元素。包含一個或多個<item>元素。
attributes:
xmlns:android
string,必須。定義xml的命名空間,必須是
“http://schemas.android.com/apk/res/android”.
<item>
定義特定狀態的color,通過它的特性指定。必須是<selector>的子元素。
attributes:
android:color
16進制顏色。必須。這個顏色由rgb值指定,可帶alpha。
這個值必須以“#”開頭,后面跟隨alpha-red-green-blue信息:
l #rgb
l #argb
l #rrggbb
l #aarrggbb
android:state_pressed
boolean。“true”表示按下狀態使用(例如按鈕按下);“false”表示非按下狀態使用。
android:state_focused
boolean。“true”表示聚焦狀態使用(例如使用滾動球/d-pad聚焦button);“false”表示非聚焦狀態使用。
android:state_selected
boolean。“true”表示選中狀態使用(例如tab打開);“false”表示非選中狀態使用。
android:state_checkable
boolean。“true”表示可勾選狀態時使用;“false”表示非可勾選狀態使用。(只對能切換可勾選—非可勾選的構件有用。)
android:state_checked
boolean。“true”表示勾選狀態使用;“false”表示非勾選狀態使用。
android:state_enabled
boolean。“true”表示可用狀態使用(能接收觸摸/點擊事件);“false”表示不可用狀態使用。
android:window_focused
boolean。“true”表示應用程序窗口有焦點時使用(應用程序在前臺);“false”表示無焦點時使用(例如notification欄拉下或對話框顯示)。
注意:記住一點,statelist中第一個匹配當前狀態的item會被使用。因此,如果第一個item沒有任何狀態特性的話,那么它將每次都被使用,這也是為什么默認的值必須總是在最后(如下面的例子所示)。
?
examples:
xml文件保存在res/color/button_text.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:color="#ffff0000"/> <!-- pressed -->
<item android:state_focused="true"
android:color="#ff0000ff"/> <!-- focused -->
<item android:color="#ff000000"/> <!-- default -->
</selector>
?
這個layout xml會應用colorstatelist到一個view上:
<button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/button_text"
android:textcolor="@color/button_text" />
?
?????? 在android上開發項目,如果僅僅是采用默認的樣式可能不是很美觀,需要編寫響應的樣式來使界面美觀,在iphone上常用的圓角ListView的實現。
??????? 本人實現的原理如下:
?通過重寫ListView中攔截觸摸的事件方式,在生成ListView時候根據不同行采用不同的樣式。如第一個行,最末一行,和中建行。(特殊的情況下只有一行的時候,四個角均為圓角考慮)。
實現如下:
?
?
最后一行為時候,下方兩個角為圓角樣式如下:
app_list_corner_round_bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#BFEEFF"
android:endColor="#40B9FF"
android:angle="270"/>
<corners android:bottomLeftRadius="6dip"
android:bottomRightRadius="6dip" />
</shape>
?
?
第一行為圓角且僅僅為一條記錄使用樣式:
app_list_corner_round.xml
?
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#BFEEFF"
android:endColor="#40B9FF"
android:angle="270"/>
<corners android:topLeftRadius="6dip"
android:topRightRadius="6dip"
android:bottomLeftRadius="6dip"
android:bottomRightRadius="6dip"/>
</shape>
?
第一行為圓角且有多條記錄使用樣式:
app_list_corner_round_top.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#BFEEFF"
android:endColor="#40B9FF"
android:angle="270"/>
<corners android:topLeftRadius="6dip"
android:topRightRadius="6dip"/>
</shape>
?
多行記錄非第一行和最末一行使用的樣式:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#BFEEFF"
android:endColor="#40B9FF"
android:angle="270"/>
</shape>
?
重寫的ListView
package com.easyway.listview.corner;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.AdapterView;
import android.widget.ListView;
/**
* 圓角ListView
* 重寫ListView的樣式實現相關的樣式
* app_list_corner_round_top.xml
* <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:startColor="#BFEEFF"
android:endColor="#40B9FF"
android:angle="270"/>
<corners android:topLeftRadius="6dip"
android:topRightRadius="6dip"/>
</shape>
*
* android:shape 配置的是圖形的形式,主要包括方形、圓形等,上邊代碼為方形。
* gradient節點主要配置起點顏色、終點顏色、中間點的坐標、中間點的顏色、漸變角度(90度為上下漸變,0為左右漸變),
* padding節點主要配置上下左右邊距,
* corners節點配置四周園角的半徑。
*
*
* @Title:
* @Description: 實現TODO
* @Copyright:Copyright (c) 2011
* @Company:易程科技股份有限公司
* @Date:2012-7-16
* @author longgangbai
* @version 1.0
*/
public class CornerListView extends ListView {
public CornerListView(Context context) {
super(context);
}
public CornerListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CornerListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 重寫此方式實現不同行的樣式不一樣
*
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
//
case MotionEvent.ACTION_DOWN:
int x = (int) ev.getX();
int y = (int) ev.getY();
//返回記錄數據行數
int itemnum = pointToPosition(x, y);
if (itemnum == AdapterView.INVALID_POSITION)
break;
else{
if(itemnum==0){
if(itemnum==(getAdapter().getCount()-1)){
setSelector(R.drawable.app_list_corner_round); //僅僅一行記錄的樣式
}else{
setSelector(R.drawable.app_list_corner_round_top); //多行且第一行的樣式
}
}else if(itemnum==(getAdapter().getCount()-1)) //最后一行的樣式
setSelector(R.drawable.app_list_corner_round_bottom);
else{
setSelector(R.drawable.app_list_corner_shape);
}
}
break;
case MotionEvent.ACTION_UP:
break;
}
return super.onInterceptTouchEvent(ev);
}
}
?
主要布局類main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:id="@+id/listview_layout"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="5dp"
android:paddingLeft="25dp"
android:paddingTop="15dp" >
<TextView
android:id="@+id/menu_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/setting"
android:textColor="@color/gray" />
</LinearLayout>
<com.easyway.listview.corner.CornerListView
android:id="@+id/list1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:background="@drawable/shape_bg_listview"
android:cacheColorHint="@null"/>
</LinearLayout>
?每行的布局:
<?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" >
<RelativeLayout
android:id="@+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dip"
android:paddingLeft="15dip"
android:paddingRight="5dip"
android:paddingTop="10dip" >
<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:textColor="@color/gray"
android:textSize="15sp" />
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="16dp"
android:src="@drawable/right" />
</RelativeLayout>
</LinearLayout>
?
主要類:
package com.easyway.listview.corner;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.SimpleAdapter;
/**
* Android實現圓角ListView示例
* 實現圓角ListView原理主要采用添加相關的樣式布局。
* 通過重寫ListView中特定的方法
* 攔截觸摸事件的方法。
* public boolean onInterceptTouchEvent(MotionEvent ev)
* 根據橫軸坐標計算行數,并實現
*
* @Title:
* @Description: 實現TODO
* @Copyright:Copyright (c) 2011
* @Company:易程科技股份有限公司
* @Date:2012-7-16
* @author longgangbai
* @version 1.0
*/
public class RoundCornerActivity extends Activity {
private CornerListView cornerListView = null;
private ArrayList<HashMap<String, String>> maplist = null;
private LinearLayout linearLayout;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//設置布局
setContentView(R.layout.main);
//獲取布局對象
linearLayout=(LinearLayout)findViewById(R.id.listview_layout);
//設置壁紙為背景圖片
linearLayout.setBackgroundDrawable(getWallpaper());
//獲取初始化數據
maplist=getData();
//創建一個適配器對象
SimpleAdapter adapter1 = new SimpleAdapter(this, maplist,
R.layout.simple_list_item_1, new String[] { "item" },
new int[] { R.id.item_title });
//創建ListView對象
cornerListView = (CornerListView) findViewById(R.id.list1);
//設置適配器
cornerListView.setAdapter(adapter1);
initListener();
}
private void initListener() {
//添加響應時間
cornerListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
if (arg2 == 0) {
System.out.println("0");
}else{
System.out.println("1");
}
}
});
}
/**
* 模擬數據
* @return
*/
public ArrayList<HashMap<String, String>> getData() {
maplist = new ArrayList<HashMap<String, String>>();
HashMap<String, String> map1 = new HashMap<String, String>();
HashMap<String, String> map2 = new HashMap<String, String>();
HashMap<String, String> map3 = new HashMap<String, String>();
HashMap<String, String> map4 = new HashMap<String, String>();
map1.put("item", "公交");
map2.put("item", "火車");
map3.put("item", "地鐵");
map4.put("item", "航空");
maplist.add(map1);
maplist.add(map2);
maplist.add(map3);
maplist.add(map4);
return maplist;
}
}
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

