1. android studio中怎麼定義一個xmlns
設置xmlns的方式有兩種:
方式一:
xmlns:app="scheme.android.com/apk/res/res-auto"
方式二:
xmlns:app="scheme.android.com/apk/res/包名"
app的名字可以任意取(只要不沖突),然後按照上述方式,在自定義的View中給屬性賦值,例如:
<cn.teachcourse.intent.utils.CircleImageViewxmlns:circle="http://schemas.android.com/apk/res/cn.teachcourse"
android:id="@+id/set_circle_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
circle:border_width="2dp"
circle:border_color="@color/colorAccent"/>
2. android中,如何做圓形的button按鈕
自己繪制圓形的圖片,然後在button布局裡面用BackgroundDrawable設置為button背景。android中是不帶圓形的button的
3. android自定義控制項怎麼用
開發自定義控制項的步驟:
1、了解View的工作原理
2、 編寫繼承自View的子類
3、 為自定義View類增加屬性
4、 繪制控制項
5、 響應用戶消息
6 、自定義回調函數
一、View結構原理
Android系統的視圖結構的設計也採用了組合模式,即View作為所有圖形的基類,Viewgroup對View繼承擴展為視圖容器類。
View定義了繪圖的基本操作
基本操作由三個函數完成:measure()、layout()、draw(),其內部又分別包含了onMeasure()、onLayout()、onDraw()三個子方法。具體操作如下:
1、measure操作
measure操作主要用於計算視圖的大小,即視圖的寬度和長度。在view中定義為final類型,要求子類不能修改。measure()函數中又會調用下面的函數:
(1)onMeasure(),視圖大小的將在這里最終確定,也就是說measure只是對onMeasure的一個包裝,子類可以覆寫onMeasure()方法實現自己的計算視圖大小的方式,並通過setMeasuredDimension(width, height)保存計算結果。
2、layout操作
layout操作用於設置視圖在屏幕中顯示的位置。在view中定義為final類型,要求子類不能修改。layout()函數中有兩個基本操作:
(1)setFrame(l,t,r,b),l,t,r,b即子視圖在父視圖中的具體位置,該函數用於將這些參數保存起來;
(2)onLayout(),在View中這個函數什麼都不會做,提供該函數主要是為viewGroup類型布局子視圖用的;
3、draw操作
draw操作利用前兩部得到的參數,將視圖顯示在屏幕上,到這里也就完成了整個的視圖繪制工作。子類也不應該修改該方法,因為其內部定義了繪圖的基本操作:
(1)繪制背景;
(2)如果要視圖顯示漸變框,這里會做一些准備工作;
(3)繪制視圖本身,即調用onDraw()函數。在view中onDraw()是個空函數,也就是說具體的視圖都要覆寫該函數來實現自己的顯示(比如TextView在這里實現了繪制文字的過程)。而對於ViewGroup則不需要實現該函數,因為作為容器是「沒有內容「的,其包含了多個子view,而子View已經實現了自己的繪制方法,因此只需要告訴子view繪制自己就可以了,也就是下面的dispatchDraw()方法;
(4)繪制子視圖,即dispatchDraw()函數。在view中這是個空函數,具體的視圖不需要實現該方法,它是專門為容器類准備的,也就是容器類必須實現該方法;
(5)如果需要(應用程序調用了setVerticalFadingEdge或者setHorizontalFadingEdge),開始繪制漸變框;
(6)繪制滾動條;
從上面可以看出自定義View需要最少覆寫onMeasure()和onDraw()兩個方法。
二、View類的構造方法
創建自定義控制項的3種主要實現方式:
1)繼承已有的控制項來實現自定義控制項: 主要是當要實現的控制項和已有的控制項在很多方面比較類似, 通過對已有控制項的擴展來滿足要求。
2)通過繼承一個布局文件實現自定義控制項,一般來說做組合控制項時可以通過這個方式來實現。
注意此時不用onDraw方法,在構造廣告中通過inflater載入自定義控制項的布局文件,再addView(view),自定義控制項的圖形界面就載入進來了。
3)通過繼承view類來實現自定義控制項,使用GDI繪制出組件界面,一般無法通過上述兩種方式來實現時用該方式。
三、自定義View增加屬性的兩種方法:
1)在View類中定義。通過構造函數中引入的AttributeSet 去查找XML布局的屬性名稱,然後找到它對應引用的資源ID去找值。
案例:實現一個帶文字的圖片(圖片、文字是onDraw方法重繪實現)
public class MyView extends View {
private String mtext;
private int msrc;
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
int resourceId = 0;
int textId = attrs.getAttributeResourceValue(null, "Text",0);
int srcId = attrs.getAttributeResourceValue(null, "Src", 0);
mtext = context.getResources().getText(textId).toString();
msrc = srcId;
}
@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.RED);
InputStream is = getResources().openRawResource(msrc);
Bitmap mBitmap = BitmapFactory.decodeStream(is);
int bh = mBitmap.getHeight();
int bw = mBitmap.getWidth();
canvas.drawBitmap(mBitmap, 0,0, paint);
//canvas.drawCircle(40, 90, 15, paint);
canvas.drawText(mtext, bw/2, 30, paint);
}
}
布局文件:
<?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" >
<com.example.myimageview2.MyView
android:id="@+id/myView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Text="@string/hello_world"
Src="@drawable/xh"/>
</LinearLayout>
屬性Text, Src在自定義View類的構造方法中讀取。
2)通過XML為View注冊屬性。與Android提供的標准屬性寫法一樣。
案例: 實現一個帶文字說明的ImageView (ImageView+TextView組合,文字說明,可在布局文件中設置位置)
public class MyImageView extends LinearLayout {
public MyImageView(Context context) {
super(context);
}
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
int resourceId = -1;
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.MyImageView);
ImageView iv = new ImageView(context);
TextView tv = new TextView(context);
int N = typedArray.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = typedArray.getIndex(i);
switch (attr) {
case R.styleable.MyImageView_Oriental:
resourceId = typedArray.getInt(
R.styleable.MyImageView_Oriental, 0);
this.setOrientation(resourceId == 1 ? LinearLayout.HORIZONTAL
: LinearLayout.VERTICAL);
break;
case R.styleable.MyImageView_Text:
resourceId = typedArray.getResourceId(
R.styleable.MyImageView_Text, 0);
tv.setText(resourceId > 0 ? typedArray.getResources().getText(
resourceId) : typedArray
.getString(R.styleable.MyImageView_Text));
break;
case R.styleable.MyImageView_Src:
resourceId = typedArray.getResourceId(
R.styleable.MyImageView_Src, 0);
iv.setImageResource(resourceId > 0 ?resourceId:R.drawable.ic_launcher);
break;
}
}
addView(iv);
addView(tv);
typedArray.recycle();
}
}
attrs.xml進行屬性聲明, 文件放在values目錄下
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyImageView">
<attr name="Text" format="reference|string"></attr>
<attr name="Oriental" >
<enum name="Horizontal" value="1"></enum>
<enum name="Vertical" value="0"></enum>
</attr>
<attr name="Src" format="reference|integer"></attr>
</declare-styleable>
</resources>
MainActivity的布局文件:先定義命名空間 xmlns:uview="http://schemas.android.com/apk/res/com.example.myimageview2" (com.example.myimageview2為你
在manifest中定義的包名)
然後可以像使用系統的屬性一樣使用:uview:Oriental="Vertical"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:uview="http://schemas.android.com/apk/res/com.example.myimageview2"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<com.example.myimageview2.MyImageView
android:id="@+id/myImageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
uview:Text="這是一個圖片說明"
uview:Src="@drawable/tw"
uview:Oriental="Vertical">
</com.example.myimageview2.MyImageView>
</LinearLayout>
四、控制項繪制 onDraw()
五、
六:自定義View的方法
onFinishInflate() 回調方法,當應用從XML載入該組件並用它構建界面之後調用的方法
onMeasure() 檢測View組件及其子組件的大小
onLayout() 當該組件需要分配其子組件的位置、大小時
onSizeChange() 當該組件的大小被改變時
onDraw() 當組件將要繪制它的內容時
onKeyDown 當按下某個鍵盤時
onKeyUp 當松開某個鍵盤時
onTrackballEvent 當發生軌跡球事件時
onTouchEvent 當發生觸屏事件時
onWindowFocusChanged(boolean) 當該組件得到、失去焦點時
onAtrrachedToWindow() 當把該組件放入到某個窗口時
onDetachedFromWindow() 當把該組件從某個窗口上分離時觸發的方法
onWindowVisibilityChanged(int): 當包含該組件的窗口的可見性發生改變時觸發的方法
4. android中這樣的曲線要怎麼繪制
繪制曲線圖首先需要畫好橫豎坐標軸建立坐標系,比如坐標系中的100距離應該在canvas中繪制多長,這個是需要計算的,其實坐標體系的建立是最復雜的,我看過很多第三方庫的建立方法都不一樣,有的要靈活一些,有的比較死板。至於繪制曲線要麼是用Canvas.drawLine方法,要麼是用Path.lineTo方法,看你自己的習慣。
為了做出一個外觀良好的曲線圖,我參考了兩個開源代碼,第一個的曲線圖繪制限制較多,使用范圍太窄,但是有數據變化時的動畫效果。第二個的適用范圍很廣,他能根據數據集合自動計算橫縱坐標的個數,在canvas上單元格的距離,只需輸入坐標點就能自動建立坐標體系繪制曲線,但是沒有動畫效果。
先講第一個LineView。
LineView的demo可以在這里下載,lineview其實只是github項目的一部分,我是將其提取出來了的,個人覺得他的其他部分沒有參考價值。作者好像是個韓國人。
LineView的曲線繪制沒有什麼可取的部分,我想學習的是他實現動畫效果的方法,設計的很好,但具體實現還需要改進,讓動畫更流暢。
Lineview的調用方法:
在xml中添加lineview控制項
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/horizontalScrollView"
android:layout_alignParentRight="true"
android:layout_above="@+id/line_button">
<view
android:layout_width="wrap_content"
android:layout_height="200dp"
class="com.example.widget.LineView"
android:id="@+id/line_view"/>
</HorizontalScrollView>
在activity代碼中獲取lineview對象:
finalLineView lineView = (LineView)findViewById(R.id.line_view);
添加橫坐標:
int randomint = 9;
ArrayList<String>test =newArrayList<String>();
for (int i=0;i<randomint; i++){
test.add(String.valueOf(i+1));
}
lineView.setBottomTextList(test);
允許繪制坐標點:
lineView.setDrawDotLine(true);
lineView.setShowPopup(LineView.SHOW_POPUPS_NONE);
ArrayList<Integer> dataList = newArrayList<Integer>();
intrandom = (int)(Math.random()*9+1);
for (int i=0;i<randomint; i++){
dataList.add((int)(Math.random()*random));
}
添加縱坐標的值:
ArrayList<ArrayList<Integer>>dataLists = newArrayList<ArrayList<Integer>>();
dataLists.add(dataList);
lineView.setDataList(dataLists);
從其用法中可以看出,lineview需要提前設定橫坐標的范圍,而且縱坐標的值必須和lineView.setBottomTextList(test)中添加的值一一對應(讀lineview源碼可以知道),使用起來很不方便,我覺得作者僅僅是做出了一條曲線而已,而不太關注是否有用。和很多曲線圖的開源代碼一樣lineview允許一次繪制幾根顏色不同的曲線。
只需在上面的代碼中為dataLists再添加一個list成員就行。
5. 求一android程序源碼 讓小球沿指定路徑運動
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;
public class MoveballActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout root = (LinearLayout)findViewById(R.id.root);
final DrawView draw = new DrawView(this);
draw.setMinimumWidth(300);
draw.setMinimumHeight(500);
draw.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View arg0, MotionEvent event){
draw.currentX = event.getX();
draw.currentY = event.getY();
draw.invalidate();
return true ;
}
});
root.addView(draw);
}
}
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class DrawView extends View{
public float currentX = 40 ;
public float currentY = 50 ;
public DrawView (Context context){
super(context);
}
public void onDraw(Canvas canvas){
super.onDraw(canvas);
//創建畫筆
Paint p = new Paint();
//設置畫筆的顏色
p.setColor(Color.RED);
//繪制一個小圓(作為小球)
canvas.drawCircle(currentX, currentY, 15, p);
}
}
跟隨手指移動的小球,參考一下吧。
6. Android自定義字母導航欄
自定義側邊字母導航欄,根據實際字母高度進行顯示
先上效果圖
public class SlideBar extends View {
//當前手指滑動到的位置
private int choosedPosition = -1;
//畫文字的畫筆
private Paint paint;
//單個字母的高度
private float perTextHeight;
//字母的字體大小
private float letterSize;
//字母的垂直間距
private float letterGap;
//字母圓形背景半徑
private float bgRadius;
private ArrayList<String> firstLetters = new ArrayList<>();
//繪制點擊時的藍色背景
private Paint backgroundPaint;
private Context context;
private OnTouchFirstListener listener;
public RecyclerView getTiku_recycle_answer() {
return tiku_recycle_answer;
}
public void setTiku_recycle_answer(RecyclerView tiku_recycle_answer) {
this.tiku_recycle_answer = tiku_recycle_answer;
}
RecyclerView tiku_recycle_answer;
public SlideBar(Context context) {
this(context, null);
}
public SlideBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlideBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SlideBar);
//字母的字體大小
letterSize = typedArray.getDimension(R.styleable.SlideBar_letter_size, DisplayUtils.sp2px(context, 10.0f));
//每個字母的高
perTextHeight = typedArray.getDimension(R.styleable.SlideBar_letter_height, DisplayUtils.dp2px(context, 10.0f));
//字母垂直間距
letterGap = typedArray.getDimension(R.styleable.SlideBar_letter_gap, DisplayUtils.dp2px(context, 6.0f));
//字母垂直間距
bgRadius = typedArray.getDimension(R.styleable.SlideBar_letter_bg_radius, DisplayUtils.dp2px(context, 8.0f));
typedArray.recycle();
init();
}
public void init() {
//初始化畫筆
paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(letterSize);
paint.setTypeface(Typeface.DEFAULT_BOLD);
//初始化圓形背景畫筆
backgroundPaint = new Paint();
backgroundPaint.setAntiAlias(true);
backgroundPaint.setColor(context.getResources().getColor(R.color.color_368FFF));
}
public void setFirstLetters(ArrayList<String> letters) {
firstLetters.clear();
firstLetters.addAll(letters);
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec); //獲取寬的模式
int heightMode = MeasureSpec.getMode(heightMeasureSpec); //獲取高的模式
int widthSize = MeasureSpec.getSize(widthMeasureSpec); //獲取寬的尺寸
int heightSize = MeasureSpec.getSize(heightMeasureSpec); //獲取高的尺寸
int width = 0;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
//如果match_parent或者具體的值,直接賦值
width = widthSize;
} else {
//如果其他模式,則指定一個寬度
width = DisplayUtils.dp2px(getContext(), 20.0f);
}
//高度跟寬度處理方式一樣
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
float textHeight = perTextHeight;
height = (int) (getPaddingTop() + textHeight * (firstLetters.size() + 1) + letterGap * (firstLetters.size() - 1) + getPaddingBottom());
}
if (height > tiku_recycle_answer.getMeasuredHeight()) {
height = tiku_recycle_answer.getMeasuredHeight();
}
//保存測量寬度和測量高度
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < firstLetters.size(); i++) {
paint.setColor(i == choosedPosition ? Color.WHITE : context.getResources().getColor(R.color.color_368FFF));
float x = (getWidth() - paint.measureText(firstLetters.get(i))) / 2;
float y = (float) getHeight() / firstLetters.size();//每個字母的高度
if (i == choosedPosition) {
canvas.drawCircle((float) (getWidth() / 2), i * y + y / 2, bgRadius, backgroundPaint);
}
//垂直位置需要增加一個偏移量,上移兩個像素,因為根據計算得到的是baseline,將字母上移,使其居中在圓內
canvas.drawText(firstLetters.get(i), x, (perTextHeight + y) / 2 + y * i-2, paint);
}
}
//觸碰事件
//按下,松開,拖動
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
this.setBackgroundColor(context.getResources().getColor(android.R.color.transparent));
float y = event.getY();
//獲取觸摸到字母的位置
choosedPosition = (int) y * firstLetters.size() / getHeight();
//上滑超過邊界,顯示第一個
if (choosedPosition < 0) {
choosedPosition = 0;
}
//下滑超過邊界,顯示最後一個
if (choosedPosition >= firstLetters.size()) {
choosedPosition = firstLetters.size() - 1;
}
if (listener != null) {
//滑動A-Z字母聯動外層數據
listener.onTouch(firstLetters.get(choosedPosition));
}
break;
case MotionEvent.ACTION_UP:
this.setBackgroundColor(context.getResources().getColor(android.R.color.transparent));
choosedPosition = -1;
if (listener != null) {
//滑動A-Z字母聯動外層數據
listener.onRelease();
}
break;
}
//重繪
invalidate();
return true;
}
public void setFirstListener(OnTouchFirstListener listener) {
this.listener = listener;
}
/**
* OnTouchFirstListener 介面
* onTouch:觸摸到了那個字母
* onRelease:up釋放時中間顯示的字母需要設置為GONE
*/
public interface OnTouchFirstListener {
void onTouch(String firstLetter);
void onRelease();
}
}
<declare-styleable name="SlideBar">
<attr name="letter_size" format="dimension" />
<attr name="letter_height" format="dimension" />
<attr name="letter_gap" format="dimension" />
<attr name="letter_bg_radius" format="dimension" />
</declare-styleable>
xml中引入,我的是constraintlayout,具體設置看自己的布局
<com.answer.view.SlideBar
android:id="@+id/slideBar"
android:layout_width="@dimen/dp_20"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/tiku_recycle_answer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guide_answer"
app:layout_constraintTop_toTopOf="@+id/tiku_recycle_answer"
app:letter_bg_radius="@dimen/dp_8"
app:letter_gap="@dimen/dp_6"
app:letter_height="@dimen/dp_10"
app:letter_size="@dimen/sp_10" />
private void handleSlideBarEvent() {
List<QuesCommentSubjectiveStuBean> datas = .getDatas();//獲取處理後的數據,賦值給導航欄
ArrayList<String> letters = new ArrayList<>();
for (QuesCommentSubjectiveStuBean stuBean : datas) {
if (letters.contains(stuBean.getFirstLetter())) {
continue;
}
letters.add(stuBean.getFirstLetter());
}
slideBar.setFirstLetters(letters);
slideBar.setTiku_recycle_answer(tiku_recycle_answer);
slideBar.setFirstListener(new SlideBar.OnTouchFirstListener() {
@Override
public void onTouch(String firstLetter, float dy) {
tv_first_letter.setVisibility(VISIBLE);
tv_first_letter.setText(firstLetter);
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) tv_first_letter.getLayoutParams();
//如果是第一個字母,修改提示框顯示位置
layoutParams.topMargin = (int) dy + slideBar.getTop() - tv_first_letter.getMeasuredHeight() / 2;
//異常情況,點擊最後一個字元,提示框顯示不全的場景,如果顯示位置超過屏幕,則靠底部顯示
if ((int) dy + slideBar.getTop() + tv_first_letter.getMeasuredHeight() / 2 > tiku_recycle_answer.getBottom()) {
layoutParams.topMargin = tiku_recycle_answer.getBottom() - tv_first_letter.getMeasuredHeight();
}
tv_first_letter.setLayoutParams(layoutParams);
//滑動後移動到對應的位置,找到第一個匹配到首字母的學生,位移到此處
int newPosition = -1;
for (QuesCommentSubjectiveStuBean stuBean : datas) {
if (firstLetter.equals(stuBean.getFirstLetter())) {
newPosition = datas.indexOf(stuBean);
break;
}
}
//move時會多次觸發,此處只響應第一次
if (newPosition != lastPosition) {
lastPosition = newPosition;
Lg.d(TAG, "questionComment-->--滑動導航欄跳轉到首字母:" + firstLetter);
subJectLinearLayoutManager.scrollToPositionWithOffset(lastPosition, 0);
}
}
@Override
public void onRelease() {
postDelayed(new Runnable() {
@Override
public void run() {
lastPosition = -1;
tv_first_letter.setVisibility(GONE);
}
}, 200);
}
});
}
5.一個小問題。
用於放大顯示選中字母的TextView在布局中,請設置為invisible,這樣在載入xml布局時,會對這個控制項進行測量和布局,只是不顯示,這樣我們才能獲得tv_first_letter.getMeasuredHeight(),如果設置為gone,不會進行測量,獲取的高度就為0,這樣在第一次顯示的時候就會有一個顯示位置跳動的異常。設置為invisible就可以解決這個問題,目的就是讓系統測量一下TextView的寬高,不想這么搞的話,在第4步之前手動測量一次也是可以的。
<TextView
android:id="@+id/tv_first_letter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_2"
android:background="@mipmap/ic_bubble"
android:fontFamily="sans-serif"
android:gravity="center"
android:text="C"
android:textColor="@color/color_ffffff"
android:textSize="@dimen/sp_18"
android:visibility="invisible"
app:layout_constraintEnd_toStartOf="@+id/guide_answer"
app:layout_constraintTop_toTopOf="parent" />
7. Android中GridView如何與廣告位輪播實現一起滑動
1.首先自定義一個ViewFlow類。
2.然後定義一個CircleFlowIndicator類。
具體代碼依然見源碼;
3.接下來就在布局文件中開始使用了
<framelayout android:id="@+id/framelayout" android:layout_height="300dip" android:layout_width="fill_parent" android:orientation="vertical">
</framelayout>代碼中有個app:activeType,app:radius 這樣的東西,可能新手不是很明白到底是個shenmegui,解釋一下這是自定義屬性。
使用自定義屬性首先要記得把這個屬性相應的命名空間給加在布局文件的開頭,否則無法編譯。
xmlns:app=」http://schemas.android.com/apk/res-auto」
這些屬性都對應在attrs.xml文件中可以找到。
4.然後就可以在Activity中調用了,具體的代碼是:
/**
* @Description:顯示廣告條的主頁
* @author http://blog.csdn.net/finddreams
*/
public class MainActivity extends Activity {
private ViewFlow mViewFlow;
private CircleFlowIndicator mFlowIndicator;
private ArrayList imageUrlList = new ArrayList();
ArrayList linkUrlArray= new ArrayList();
ArrayList titleList= new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
imageUrlList.add(https://gss0..com/9vo3dSag_xI4khGko9WTAnF6hhy/image/pic/item/.jpg);
imageUrlList.add(https://gss0..com/-fo3dSag_xI4khGko9WTAnF6hhy/image/pic/item/.jpg);
imageUrlList.add(https://gss0..com/-Po3dSag_xI4khGko9WTAnF6hhy/image/pic/item/.jpg);
linkUrlArray.add(http://blog.csdn.net/finddreams/article/details/44301359);
linkUrlArray.add(http://blog.csdn.net/finddreams/article/details/43486527);
linkUrlArray.add(http://blog.csdn.net/finddreams/article/details/43194799);
titleList.add(Android開發面試經——);
titleList.add(Android控制項GridView之仿支付寶錢包首頁帶有分割線的GridView九宮格的完美實現);
titleList.add(Android動畫之仿美團載入數據等待時,小人奔跑進度動畫對話框 );
initBanner(imageUrlList);
}
private void initView() {
mViewFlow = (ViewFlow) findViewById(R.id.viewflow);
mFlowIndicator = (CircleFlowIndicator) findViewById(R.id.viewflowindic);
}
private void initBanner(ArrayList imageUrlList) {
mViewFlow.setAdapter(new ImagePagerAdapter(this, imageUrlList,
linkUrlArray, titleList).setInfiniteLoop(true));
mViewFlow.setmSideBuffer(imageUrlList.size()); // 實際圖片張數,
// ImageAdapter實際圖片張數為3
mViewFlow.setFlowIndicator(mFlowIndicator);
mViewFlow.setTimeSpan(4500);
mViewFlow.setSelection(imageUrlList.size() * 1000); // 設置初始位置
mViewFlow.startAutoFlowTimer(); // 啟動自動播放
}
}
5.有一個很關鍵的就是ImagePagerAdapter這個適配器,因為載入網路圖片是在這個類里實現的,還有廣告條的點擊,進入一個Web界面的實現。在這里載入網路圖片使用了一個很火的開源項目,UniversalImageLoader(非同步載入網路圖片) 。
ImagePagerAdapter.class 類:
/**
* @Description: 圖片適配器
* @author http://blog.csdn.net/finddreams
*/
public class ImagePagerAdapter extends BaseAdapter {
private Context context;
private List imageIdList;
private List linkUrlArray;
private List urlTitlesList;
private int size;
private boolean isInfiniteLoop;
private ImageLoader imageLoader;
private DisplayImageOptions options;
public ImagePagerAdapter(Context context, List imageIdList,
List urllist, List urlTitlesList) {
this.context = context;
this.imageIdList = imageIdList;
if (imageIdList != null) {
this.size = imageIdList.size();
}
this.linkUrlArray = urllist;
this.urlTitlesList = urlTitlesList;
isInfiniteLoop = false;
// 初始化imageLoader 否則會報錯
imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_launcher) // 設置圖片下載期間顯示的圖片
.showImageForEmptyUri(R.drawable.meinv) // 設置圖片Uri為空或是錯誤的時候顯示的圖片
.showImageOnFail(R.drawable.meinv) // 設置圖片載入或解碼過程中發生錯誤顯示的圖片
.cacheInMemory(true) // 設置下載的圖片是否緩存在內存中
.cacheOnDisc(true) // 設置下載的圖片是否緩存在SD卡中
.build();
}
@Override
public int getCount() {
// Infinite loop
return isInfiniteLoop ? Integer.MAX_VALUE : imageIdList.size();
}
/**
* get really position
*
* @param position
* @return
*/
private int getPosition(int position) {
return isInfiniteLoop ? position % size : position;
}
@Override
public View getView(final int position, View view, ViewGroup container) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = holder.imageView = new ImageView(context);
holder.imageView
.setLayoutParams(new ViewGroup.LayoutParams(-1, -1));
holder.imageView.setScaleType(ImageView.ScaleType.FIT_XY);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
imageLoader.displayImage(
(String) this.imageIdList.get(getPosition(position)),
holder.imageView, options);
holder.imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String url = linkUrlArray.get(ImagePagerAdapter.this
.getPosition(position));
String title = urlTitlesList.get(ImagePagerAdapter.this
.getPosition(position));
/*
* if (TextUtils.isEmpty(url)) {
* holder.imageView.setEnabled(false); return; }
*/
Bundle bundle = new Bundle();
bundle.putString(url, url);
bundle.putString(title, title);
Intent intent = new Intent(context, BaseWebActivity.class);
intent.putExtras(bundle);
context.startActivity(intent);
Toast.makeText(context, 點擊了第 + getPosition(position) ,
0).show();
}
});
return view;
}
private static class ViewHolder {
ImageView imageView;
}
/**
* @return the isInfiniteLoop
*/
public boolean isInfiniteLoop() {
return isInfiniteLoop;
}
/**
* @param isInfiniteLoop
* the isInfiniteLoop to set
*/
public ImagePagerAdapter setInfiniteLoop(boolean isInfiniteLoop) {
this.isInfiniteLoop = isInfiniteLoop;
return this;
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
}
6.點擊進入一個帶進度條的WebView的Activity,載入成功就可以了。