1. 程式人生 > >自定義控制元件三部曲檢視篇(四)——RecyclerView系列之一簡單使用

自定義控制元件三部曲檢視篇(四)——RecyclerView系列之一簡單使用

絕望的時候不要那麼絕望,高興的時候不要那麼高興,是你慢慢會學會的。 ——董卿

轉了一年多,又回來繼續做Android。果然還是看到程式碼最讓我興奮……但有些事,沒經歷過,總歸還是遺憾的。在VIVO的遊戲中心,有一個特別炫酷的功能:

Vivo遊戲空間效果

這個功能就是使用RecyclerView來實現的,在本系列中,我們將最終制作出這樣的一個效果出來。

一、匯入Support-v7包

工欲善其事必先利其器,RecyclerView存在於support-v7包中,我們需要在新建的gradle工程中匯入support-v7包:

compile 'com.android.support:recyclerview-v7:21.0.3'

gralde 版本較高的同學,會發現compile關鍵字這裡會報警告,在高版本gradle中compile已經棄用了,改成了implementation,所以你可以改為:

implementation 'com.android.support:recyclerview-v7:21.0.3'

加上上面的依賴程式碼以後,會發現根本不好使,依賴庫根本拉不下來。這是為什麼呢?

support-v7包並不是通過maven從遠端下載的,而是通過Android Studio的SDK Manager來下載到本地,然後再引用的。本地有沒有support-v7包,大家可以看下SDK的這個位置(Sdk\extras\android\m2repository\com\android\support):

這裡寫圖片描述
從這裡可以看到,在我的com/android/support目錄下有所有的support包,這裡也有recyclerview-v7包。如果在該資料夾下,你沒有的話,可以通過SDK Manager引入:
這裡寫圖片描述
下載完成後,在這個資料夾下就會有對應的包存在了,當我們點進去recyclerview-v7資料夾裡面,可以看到各種版本:
這裡寫圖片描述
大家就可以選擇這裡已有的版本引入了,比如我這裡是有25.3.1的,所以我這裡最終的引用包是:

implementation 'com.android.support:recyclerview-v7:25.3.1'

在引入support包時,需要有兩個注意事項:

  • 引入的support包的版本要比targetSdkVersion要高,不然會報錯
  • 如果引入了多個support包元件,它們的版本號要保持一致,不然有可能因為不是同一個版本,程式碼不配套而出現錯誤,比如我同時引入appcompat包和recyclerview包,那麼它們的寫法應該是:
implementation 'com.android.support:appcompat-v7:25.3.1'
implementation 'com.android.support:recyclerview-v7:25.3.1'

二、簡單使用

在這部分,我們首先做出一個最簡單的例子,來看下RecyclerView的使用方法。本小節所實現的效果如下圖所示:

這裡寫圖片描述

2.1 引入RecyclerView

首先,在XML中引入RecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LinearActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/linear_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>

</android.support.constraint.ConstraintLayout>

2.2 實現Adapter

與listView一樣,同樣需要一個Adapter來將資料和Item檢視繫結起來,但不同的的是RecyclerView的Adapter需要派生自RecyclerView.Adapter<RecyclerView.ViewHolder>

當我們寫一個Adapter的類派生自RecyclerView.Adapter<RecyclerView.ViewHolder>時,最簡單的形式是這樣的:

public class RecyclerAdapter extends RecyclerView.Adapter<ViewHolder> {
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return null;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

    }

    @Override
    public int getItemCount() {
        return 0;
    }
}

這三個函式是強制必須重寫的,其中:

  • onCreateViewHolder:用於得到我們自定義的ViewHolder,在listView中,我們也會定義ViewHolder來承載檢視中的元素.
  • onBindViewHolder:是用於將指定位置的資料和檢視繫結起來的
  • getItemCount:用於獲取列表總共的item數

可見,這三項其實在listview中也都是需要做的,只是這裡單獨通過回撥給列出來了,我們只需要補充上這三個函式,就算實現了Adapter了.

在填充RecyclerAdapter之前,我們知道,一般而言ListView的資料都是從外部傳進來的,所以我們需要給RecyclerAdapter新增上一個建構函式,將資料從外部傳進來:

private Context mContext;
private ArrayList<String> mDatas;

public RecyclerAdapter(Context context, ArrayList<String> datas) {
    mContext = context;
    mDatas = datas;
}

為了方便起來,我們傳進來的資料非常簡單,就是一個String字串,同時,由於在RecyclerAdater中,經常會用到Context,所以我們也把Context傳進來,並且儲存起來.

接下來,我們就是先建立一個HolderView,然後填充那三個函式。我們都知道HolderView主要是為了儲存每一個Item的檢視的控制元件元素。所以我們要先建立一個Item的xml(item_layout.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="wrap_content">

    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="10dp" />

</LinearLayout>

在這個item中,只有一個TextView,所以我們先寫一個ViewHolder,ViewHolder的主要作用就是將XML中的控制元件以變數的形式儲存起來,方便我們後面資料繫結.

public class NormalHolder extends RecyclerView.ViewHolder{
        public TextView mTV;

        public NormalHolder(View itemView) {
            super(itemView);

            mTV = (TextView) itemView.findViewById(R.id.item_tv);
            mTV.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext,mTV.getText(),Toast.LENGTH_SHORT).show();
                }
            });

        }
    }

在這裡,在建立ViewHolder時,將整個ItemView傳了進來,然後將TextView從ItemView中取出來儲存在mTV變數中.並且,在點選mTV後,彈出這個TextView的內容.

在寫好ViewHolder以後,我們就要逐個填充RecyclerAdapter的三個函數了。首先是onCreateViewHolder:

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(mContext);
    return new NormalHolder(inflater.inflate(R.layout.item_layout,parent,false));
}

在每一次需要建立ViewHolder時,都會呼叫onCreateViewHolder函式,所以我們需要在onCreateViewHolder中返回我們建立的ViewHolder例項。

然後在onBindViewHolder中,將資料與ViewHolder繫結起來:

public void onBindViewHolder(ViewHolder holder, int position) {
    NormalHolder normalHolder = (NormalHolder)holder;
    normalHolder.mTV.setText(mDatas.get(position));
}

最後,在getItemCount中返回資料的個數:

public int getItemCount() {
    return mDatas.size();
}

到這裡,整個RecyclerAdapter就實現完了,完整的程式碼如下,供大家參考:

public class RecyclerAdapter extends RecyclerView.Adapter<ViewHolder> {

    private Context mContext;
    private ArrayList<String> mDatas;

    public RecyclerAdapter(Context context, ArrayList<String> datas) {
        mContext = context;
        mDatas = datas;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        return new NormalHolder(inflater.inflate(R.layout.item_layout, parent, false));
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        NormalHolder normalHolder = (NormalHolder) holder;
        normalHolder.mTV.setText(mDatas.get(position));
    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    public class NormalHolder extends RecyclerView.ViewHolder {
        public TextView mTV;

        public NormalHolder(View itemView) {
            super(itemView);

            mTV = (TextView) itemView.findViewById(R.id.item_tv);
            mTV.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext, mTV.getText(), Toast.LENGTH_SHORT).show();
                }
            });

        }
    }
}

2.3 填充RecyclerView

之後,回到Activity中,首先,構造一個模擬資料的函式,用於填充RecyclerVIew:

public class LinearActivity extends AppCompatActivity {
	…………
	private ArrayList<String> mDatas =new ArrayList<>();
	private void generateDatas(){
	    for (int i=0;i<200;i++){
	        datas.add("第 " + i +" 個item");
	    }
	}
}

之後,在OnCreate函式中填充RecyclerView:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_linear);

    generateDatas();
    RecyclerView mRecyclerView = (RecyclerView)findViewById(R.id.linear_recycler_view);
   
    //線性佈局
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    mRecyclerView.setLayoutManager(linearLayoutManager);

    RecyclerAdapter adapter = new RecyclerAdapter(this, mDatas);
    mRecyclerView.setAdapter(adapter);
}

這裡與listVIew唯一的區別是,這裡需要設定一個LayoutManager物件,這裡設定的是LinearLayoutManager,也就是垂直列表。我們知道Adapter的職責是用資料將每個Item的控制元件填充起來。而RecycerView與ListView不一樣的是,它不僅能實現傳統的滑動的列表,還能實現GridView和瀑布流造型,或者其它各式各樣的特殊造型。而這些造型的實現就是通過LayoutManger來實現的,我們通過Adapter將Item填充了以後,那每個Item怎麼擺放是由誰來做的呢?擺放Item的操作就是使用LayoutManager來實現出來的。所以每個LayoutManger所實現的擺放Item的方式都是不一樣的,比如:LinearLayoutManager就是傳統的ListView的功能,上下滾動或者左右滾動。而GridLayoutManager則是網格擺放,而StaggeredGridLayoutMnager則是瀑布流擺放。

到這裡,我們就實現了本部分開頭的上下滾動的效果了。

*原始碼在文章底部給出

三、其它LayoutManager

從上面的分析可以看出,擺放Item的操作主要是由LayoutManager來實現的,這也就是RecyclerView可以製作出各種特殊列表樣式的原因。系統為我們提供了幾個已經寫好的LayoutManager:

這裡寫圖片描述

其中WearableLinearLayoutManager用於在穿戴裝置上使用,比如智慧手錶等,所以我們這裡不討論它。下面我們逐個看下這些LayoutManger所實現的效果。

3.1 GridLayoutManager

我們知道了,LayoutManger的職責就是如何擺放Item,所以對於Adapter與RecyclerView是沒有影響的,除非我們為了迎合LayoutManger要改Item的佈局,比如為了實現瀑布流效果而需要改變每個Item的寬或高等。一般而言,我們更改LayoutManager,不需要對其它物件操作。所以這也是RecyclerView比較好的一個地方,通過RecycerView本身,Adapter,LayoutManger實現了完全解耦。各自實現各自的功能,與其它部分無關。而GridLayoutManager的主要作用就是將Item進行網格狀擺放,進而實現網格佈局效果。

所以我們要設定GridLayoutManager時,也只需要更改Acitivity中的設定LayoutManager這塊程式碼即可,其它都不需要動:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_grid);

    generateDatas();
    RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.grid_recycler_view);

    //如果是橫向滾動,後面的數值表示的是幾行,如果是豎向滾動,後面的數值表示的是幾列
    GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 5);
    gridLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    mRecyclerView.setLayoutManager(gridLayoutManager);

    RecyclerAdapter adapter = new RecyclerAdapter(this, mDatas);
    mRecyclerView.setAdapter(adapter);
}

private void generateDatas() {
    for (int i = 0; i < 200; i++) {
        mDatas.add("第 " + i + " 個item");
    }
}

其中:
public GridLayoutManager(Context context, int spanCount)

  • spanCount:如果是豎向滾動,則表示當前劃分為幾列;如果是橫向滾動,則表示當前劃分為幾行。

效果如下:

這裡寫圖片描述

可以看到,這裡就實現了網格效果,並且是上下滾動。我們通過gridLayoutManager.setOrientation();可以設定RecyclerView的滾動方向,取值有LinearLayoutManager.VERTICAL和LinearLayoutManager.HORIZONTAL

如果我們將它改為橫向滾動:

GridLayoutManager gridLayoutManager = new GridLayoutManager(this,5);
gridLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
mRecyclerView.setLayoutManager(gridLayoutManager);

效果如下:

這裡寫圖片描述

在橫向滾動的情況下,列表就變成了五行了。

3.2 StaggeredGridLayoutMnager

StaggeredGridLayoutMnager主要用來實現瀑布流效果。同樣,我們直接把LayoutManager改為StaggeredGridLayoutMnager:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_staggered);

    generateDatas();
    RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.stagger_recycler_view);
    //瀑布流佈局
    StaggeredGridLayoutManager staggeredManager = new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.VERTICAL);
    mRecyclerView.setLayoutManager(staggeredManager);
    ……
}

其中 public StaggeredGridLayoutManager(int spanCount, int orientation)

  • spanCount:同樣表示行數或列數,如果是豎向滾動,則表示當前劃分為幾列;如果是橫向滾動,則表示當前劃分為幾行。
  • orientation:表示滾動方向,取值有:StaggeredGridLayoutManager.HORIZONTAL和StaggeredGridLayoutManager.VERTICAL

下面來看下效果:

這裡寫圖片描述

可以看到,這裡由於每個Item的高度是一定的,所有的Item的高度都一樣,導致所實現的瀑布流佈局跟網格佈局完全相同,所以如果想實現瀑布流佈局,那必然需要每個Item的高度是不一樣的。

所以我們需要修改Adapter,在程式碼中動態設定每個Item的高度,讓每個Item的高度儘量都不一樣,這樣就可以看到瀑布流效果了。

所以,主要修改了這兩個地方:

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    NormalHolder normalHolder = (NormalHolder)holder;
    normalHolder.mTV.setText(mDatas.get(position));

    ViewGroup.LayoutParams lp = normalHolder.mTV.getLayoutParams();
    lp.height = getRandomHeight();
    normalHolder.mTV.setLayoutParams(lp);
}

private int getRandomHeight(){
    int randomHeight = 0;
    do{
        randomHeight = (int)(Math.random()*300);
    }while (randomHeight == 0);
    return randomHeight;
}

定義了一個getRandomHeight()函式,得到一個0-300之間的一個數值。然後在onBindViewHolder中,將這個數值設定給TextView,作為TextVIew的高度。

完整的改寫後的Adapter的程式碼如下:

public class StaggerRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private Context mContext;
    private ArrayList<String> mDatas;

    public StaggerRecyclerAdapter(Context context, ArrayList<String> datas) {
        mContext = context;
        mDatas = datas;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        return new NormalHolder(inflater.inflate(R.layout.item_layout, parent, false));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        NormalHolder normalHolder = (NormalHolder) holder;
        normalHolder.mTV.setText(mDatas.get(position));

        ViewGroup.LayoutParams lp = normalHolder.mTV.getLayoutParams();
        lp.height = getRandomHeight();
        normalHolder.mTV.setLayoutParams(lp);
    }

    private int getRandomHeight() {
        int randomHeight = 0;
        do {
            randomHeight = (int) (Math.random() * 300);
        } while (randomHeight == 0);
        return randomHeight;
    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    public class NormalHolder extends RecyclerView.ViewHolder {
        public TextView mTV;

        public NormalHolder(View itemView) {
            super(itemView);

            mTV = (TextView) itemView.findViewById(R.id.item_tv);
            mTV.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext, mTV.getText(), Toast.LENGTH_SHORT).show();
                }
            });

        }
    }
}

改寫後的效果如下:

這裡寫圖片描述

首先,可以看到,這裡已經實現了瀑布流效果,但是每當滾動到頂部時,所有的Item會跳動一下,重新佈局,這是為什麼呢?

這是因為在每次拉到頂部的時候,所有的Item會重新執行一次onBindViewHolder函式,因為我們Item的高度就是在這個函式中隨機生成的,所以在拉到頂部時,每個Item的高度就會重新生成,造成的結果就是看起來跳了一下,重新佈局了。

所以,要解決這個問題也比較簡單,那就是用一個數組,在Adapter初始化的時候,就把每個Item的高度生成好,然後在onBindViewHolder中直接取出即可。

所以,我們可以先申請一個數組,並且在Adapter初始化時,儲存每個Item的高度

public class StaggeredRecyclerAdapter extends Adapter<ViewHolder> {

    private Context mContext;
    private ArrayList<String> mDatas;
    private ArrayList<Integer> mHeights = new ArrayList<>();

    public StaggeredRecyclerAdapter
            
           

相關推薦

定義控制元件三部曲檢視——RecyclerView系列之一簡單使用

絕望的時候不要那麼絕望,高興的時候不要那麼高興,是你慢慢會學會的。 ——董卿 轉了一年多,又回來繼續做Android。果然還是看到程式碼最讓我興奮……但有些事,沒經歷過,總歸還是遺憾的。在VIVO的遊戲中心,有一個特別炫酷的功能: 這個功能就是使

定義控制元件三部曲檢視——RecyclerView系列之二ItemDecoration

從來不跌倒不算光彩,每次跌倒後能再站起來,才是最大的榮耀。 一、新增分割線 1.1 引入ItemDecoration 在上一篇中,我們講解了RecyclerView的基本使用方法,但有個問題:為什麼Item之間沒有分割線呢?其實,給RecyclerView新

定義控制元件三部曲檢視——瀑布流容器WaterFallLayout實現

前言:只要在前行,夢想就不再遙遠 系列文章: 前面兩節講解了有關ViewGroup的onMeasure、onLayout的知識,這節我們深入性地探討一下,如何實現經常見到的瀑布流容器,本節將實現的效果圖如下: 從效果圖中可以看出這裡要完成的

定義控制元件之繪圖:canvas變換與操作

前言:前幾篇講解了有關canvas繪圖的一些操作,今天更深入一些,講講對畫布的操作,這篇文章不像前幾篇那麼容易理解,如果以前沒有接觸過畫布的童鞋可能比較難以理解,為什麼會這樣。我儘量多畫圖,讓大家更清晰明白。前幾天偶然看到一篇文章,寫的樸實無華,充滿正能量,我非常喜歡裡面的一

定義控制元件之繪圖:區域Range

前言:最近幾天對畫圖的研究有些緩慢,專案開始寫程式碼了,只能在晚上空閒的時候捯飭一下自己的東西,今天給大家講講區域的相關知識,已經想好後面兩篇的內容了,這幾天有時間趕緊寫出來給大家。有關介面開發的東東內容確實比較多,慢慢來吧,總有一天會不一樣。我自己的一句警言,送給大家:想要

C#定義控制元件程式設計輕鬆入門1

前 言 話說,許多新手在接觸C#的時候都覺得C#使用起來特別容易方便,相對C++來說沒有那麼多的繁瑣,比如C++每次在使用一個函式,都要先在標頭檔案中宣告一遍,而C#宣告和實現都在一起,立馬可以用。而且不會一會要寫指標一會兒要寫引用,如果是遇到VC那些控制代碼就把頭給搞大。 隨著

十九c#Winform定義控制元件-下拉框表格

前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制元件,於是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_contr

定義控制元件三部曲之繪圖——Path之貝賽爾曲線和手勢軌跡、水波紋效果

前言:好想義無反顧地追逐夢想從這篇開始,我將延續androidGraphics系列文章把圖片相關的知識給大家講完,這一篇先稍微進階一下,給大家把《android Graphics(二):路徑及文字》略去的quadTo(二階貝塞爾)函式,給大家補充一下。 本篇最終將以兩個例子給

定義控制元件三部曲之動畫——alpha、scale、translate、rotate、set的xml屬性及用法

前言:這幾天做客戶回訪,感觸很大,使用者只要是留反饋資訊,總是一種恨鐵不成鋼的心態,想用你的app,卻是因為你的技術問題,讓他們不得不放棄,而你一個回訪電話卻讓他們盡釋前嫌,當最後把手機號留給他們以便隨時溝通的時候,總會發來一條條的鼓勵簡訊,讓我不自主的開始內疚。哎,多麼可愛

定義控制元件三部曲之繪圖十三——Canvas與圖層(一)

前言:猛然知道姥姥79了,我好怕,好想哭系列文章:一、如何獲得一個Canvas物件方法一:自定義view時, 重寫onDraw、dispatchDraw方法(1)、定義 我們先來看一下onDraw、dispatchDraw方法的定義protected void onDraw(

定義控制元件三部曲之動畫——Interpolator插值器

前言:雖然我不太能欣賞的了帕爾哈提的音樂,但我確實很欣賞他的人生態度,專心做自己,不想名利得失,有一天,你想要的東西都會來。其實我覺得,人生最可怕的就是停止不前,只要一直前行,總有一天會到達人生巔峰。相關文章:一、概述Interpolator屬性是Animation類的一個X

定義控制元件三部曲之動畫(十一)——layoutAnimation與gridLayoutAnimation

前言:人或許天生是懶惰的,明知道的不足,卻不努力彌補。 前幾篇給大家講述瞭如何針對某一個控制元件應用動畫,這篇將給大家講解如何給容器中的控制元件應用統一動畫。即在容器中控制元件出現時,不必為每個控制元件新增進入動畫,可以在容器中為其新增統一的進入和

定義控制元件三部曲之繪圖(二十)——RadialGradient與水波紋按鈕效果

前言:每當感嘆自己的失敗時,那我就問你,如果讓你重新來一次,你會不會成功?如果會,那說明並沒有拼盡全力。 系列文章: 最近博主實在是太忙了,部落格更新實在是太慢了,真是有愧大家。 這篇將是Shader的最後一篇,下部分,我們將講述Canvas變

定義控制元件三部曲之動畫(十)——聯合動畫的XML實現與使用示例

前言:不畏人生,或許才能方得始終;大膽拼,大膽闖是要有一定資本的,在能力不到的時候,就只有選擇忍氣吞聲! 上篇給大家講了有關AnimatorSet的程式碼實現方法,這篇我們就分別來看看如何利用xml來實現ValueAnimator、ObjectAn

定義控制元件 輪盤 來源於GITHUB記錄,筆記

自定義控制元件:輪盤抽獎 -------邏輯程式碼(輪盤的類)首先要寫一個類繼承SurfaceView 實現Callback和Runnable方法: //所使用的包 import android.content.Context; import android.graphics.Ca

定義控制元件 輪盤 來源於GITHUB記錄,筆記

自定義控制元件:輪盤抽獎 -------邏輯程式碼(輪盤的類)首先要寫一個類繼承SurfaceView 實現Callback和Runnable方法: //所使用的包 import android.content.Context; import android.

Android定義控制元件--圓形進度條中間有圖diao

智慧家居越來越流行,在智慧家居中我們常要表現一些資料的百分比 圓形度條中間加個圖是一種非常流行的自定義View 1.第一步 你首先需要對類進行繼承View public class CircleProgressImageView extends View 2.第二步 要實

Android定義控制元件之入門---整理網路上的資源

前言, 我的視訊系列 http://edu.csdn.net/course/detail/2741, 一起來學習Android… 本篇部落格主要是想要講解一下自定義控制元件如何入門,其中有好多資料資源來源自網路,綜合了網路上一些有些的博文

定義控制元件之繪圖:Canvas與圖層(二)

public class CLIP_TO_LAYER_SAVE_FLAG_VIEW extends View {       private Paint mPaint;       public CLIP_TO_LAYER_SAVE_FLAG_VIEW(Context context, Att

Qt編寫定義控制元件37-發光按鈕會呼吸的痛

一、前言 這個控制元件是好早以前寫的,已經授權過好幾個人開源過此控制元件程式碼,比如紅磨坊小胖,此控制元件並不是來源於真實需求,而