★16.容器視圖

ViewGroup

視圖組

  • LinearLayout:線性布局。
  • TableLayout:表格布局,包含多個TableRow晾捏,每個TableRow能包含多個子視圖。
  • RelativeLayout:用于調(diào)整子視圖與子視圖之間的位置間隔哀托。
  • FrameLayout:用做占位符惦辛,此Layout的子視圖都會錨定在左上角。

視圖組參數(shù)

RecycleView

可定制項

xml文件

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

ViewHolder

簡介

  • ViewHolder有個itemView私有成員,可以從itemView中通過findViewById()找到子View雨女。
  • 保留context注意內(nèi)存泄漏問題谚攒,可以使用ApplicationContext
  • 此處context非必要氛堕。

簡單示例

@SuppressWarnings({"FieldCanBeLocal", "unused"})
class Holder extends RecyclerView.ViewHolder {
    private Context mContext;
    // Todo: View成員
    // Todo: Model成員

    Holder(Context context, View itemView) {
        super(itemView);
        bindView(itemView);
        mContext = context;
    }

    void bindModel(/* Model */) {
        // Todo: 初始化Model
        // Todo: 綁定View和Model
    }

    void setOnClickListener(View.OnClickListener onClickListener) {
        itemView.setOnClickListener(onClickListener);
    }

    private void bindView(View itemView) {
        // Todo: 初始化View
    }
}

Adapter

簡介

  • 保留context注意內(nèi)存泄漏問題馏臭,可以使用ApplicationContext
  • 此處context非必要讼稚。

簡單示例

public class Adapter extends RecyclerView.Adapter<Holder> {
    private Context mContext;
    // Todo: Models

    // Todo: 構(gòu)造
    public Adapter(Context context, /* Models */) {
        mContext = context;
        // 初始化Models
    }

    @Override
    public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        // Todo: 載入布局
        View view = layoutInflater.inflate(/*View Layout Id*/, parent, false);
        return new Holder(mContext, view);
    }

    @Override
    public void onBindViewHolder(Holder holder, int position) {
        // Todo: Get Model in Models by Position
        // Todo: Bind Model and Holder
    }

    @Override
    public int getItemCount() {
        // Todo: return Size
        return /* Size */;
    }
}

LayoutManager

LinearLayoutManager

RecyclerView mRecyclerView = /* 初始化 */;
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

GridLayoutManager

RecyclerView mRecyclerView = /* 初始化 */;
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2, GridLayoutManager.VERTICAL, false));

StaggeredGridLayoutManager

RecyclerView mRecyclerView = /* 初始化 */;
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));

ItemDecoration

簡介

  • 用于定制繪制子項行為
  • 繪制順序:onDraw()-> 子項 ->onDrawOver()

簡單示例

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <size android:height="2dp"/>
    <solid android:color="#8b2cab"/>
</shape>
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
    private Drawable mDivider;

    public DividerItemDecoration(Context context) {
        mDivider = context.getResources().getDrawable(R.drawable.d, null);
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();
        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount - 1; i++) {
            View child = parent.getChildAt(i);
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            int top = child.getBottom() + params.bottomMargin;
            int bottom = top + mDivider.getIntrinsicHeight();
            // 設(shè)置mDivider的繪畫區(qū)域和寬高括儒,相當于給定左上角和右下角坐標確定一個矩形
            mDivider.setBounds(left, top, right, bottom);
            // 在畫布(Canvas)上畫
            mDivider.draw(c);
        }
    }

    @Override
    public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
    }

    // Item偏移
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (parent.getAdapter().getItemCount() - 1 == parent.getChildAdapterPosition(view))
            outRect.set(0, 0, 0, 0);
        else {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        }
    }
}

ItemAnimator

  • 用于定制子項動畫增刪。
  • 通過復制粘貼DefaultItemAnimator并重寫其中的幾個函數(shù)來控制動畫
    • animateRemoveImpl
    • animateAddImpl
    • animateMoveImpl
    • animateChangeImpl
    • endAnimation:恢復原狀
    • endAnimations:恢復原狀
  • 因為復用的原因乱灵,子項動畫處理完畢后必須恢復原狀塑崖。
  • 【Todo】:可以封裝

RecyclerView

RecyclerView mRecyclerView = /* 初始化 */;
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity()));
Adapter adapter = new Adapter(getActivity(), /* Models */);
mRecyclerView.setAdapter(adapter);

顯示沒有內(nèi)容

  • 有以下兩種方式:
    • 教程七冲。
    • 動態(tài)加載痛倚。

注意事項

  • 對于因為復用導致索引錯亂的問題,使用ViewHolder.getAdapterPosition()解決澜躺。若找不到ViewHolder蝉稳,會返回-1,注意處理這種情況掘鄙。
  • 項目發(fā)生改變時( 增加 耘戚、 刪除修改 )操漠,記得調(diào)用notify()系列函數(shù)收津。

ViewPager

xml文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

FragmentStatePagerAdapter

FragmentManager fragmentManager = getSupportFragmentManager();
mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
    @Override
    public Fragment getItem(int position) {
        return /* fragment */;
    }

    // 獲取當前的顯示的那一頁的Fragment
    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
        mPageFragment = (PageFragment) object;
    }

    @Override
    public int getCount() {
        return /* size */;
    }
});

FragmentPagerAdapter

  • 相對比于FragmentStatePagerAdapterFragmentPagerAdapter不會回收復用浊伙。
  • 使用方法參見FragmentStatePagerAdapter撞秋。

PagerAdapter

@SuppressWarnings("WeakerAccess")
public class CustomPagerAdapter extends PagerAdapter {
    private Context mContext;

    public CustomPagerAdapter(Context context) {
        mContext = context;
    }

    @Override
    public Object instantiateItem(ViewGroup collection, int position) {
        LayoutInflater inflater = LayoutInflater.from(mContext);
        ViewGroup layout = (ViewGroup) inflater.inflate(/* Layout */, collection, false);
        collection.addView(layout);
        return layout;
    }

    @Override
    public void destroyItem(ViewGroup collection, int position, Object view) {
        collection.removeView((View) view);
    }

    @Override
    public int getCount() {
        return /* size */;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}

常用方法

  • setCurrentItem():設(shè)置當前頁數(shù)。
  • setOffscreenPageLimit():預加載頁數(shù)嚣鄙。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吻贿,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子哑子,更是在濱河造成了極大的恐慌舅列,老刑警劉巖肌割,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異帐要,居然都是意外死亡把敞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門榨惠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來先巴,“玉大人,你說我怎么就攤上這事冒冬∩祢牵” “怎么了?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵简烤,是天一觀的道長剂邮。 經(jīng)常有香客問我,道長横侦,這世上最難降的妖魔是什么挥萌? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮枉侧,結(jié)果婚禮上引瀑,老公的妹妹穿的比我還像新娘。我一直安慰自己榨馁,他們只是感情好憨栽,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著翼虫,像睡著了一般屑柔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上珍剑,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天掸宛,我揣著相機與錄音,去河邊找鬼招拙。 笑死唧瘾,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的别凤。 我是一名探鬼主播饰序,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闻妓!你這毒婦竟也來了菌羽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎注祖,沒想到半個月后猾蒂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡是晨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年肚菠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片罩缴。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡蚊逢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出箫章,到底是詐尸還是另有隱情烙荷,我是刑警寧澤,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布檬寂,位于F島的核電站终抽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏桶至。R本人自食惡果不足惜昼伴,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望镣屹。 院中可真熱鬧圃郊,春花似錦、人聲如沸女蜈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鞭光。三九已至吏廉,卻和暖如春泞遗,著一層夾襖步出監(jiān)牢的瞬間惰许,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工史辙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留汹买,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓聊倔,卻偏偏與公主長得像晦毙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子耙蔑,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,799評論 25 707
  • 簡介: 提供一個讓有限的窗口變成一個大數(shù)據(jù)集的靈活視圖见妒。 術(shù)語表: Adapter:RecyclerView的子類...
    酷泡泡閱讀 5,148評論 0 16
  • Tangram是阿里出品、用于快速實現(xiàn)組合布局的框架模型甸陌,在手機天貓Android&iOS版 內(nèi)廣泛使用 該框架提...
    wintersweett閱讀 3,268評論 0 1
  • 前言 ListView在Android開發(fā)中十分常見 今天须揣,我將為大家?guī)鞮istView與AdapterView...
    Carson帶你學安卓閱讀 42,577評論 21 216
  • 想家的時候比較多盐股, 是在比較冷的天, 才想擁有棉拖耻卡。 可笑吧疯汁, 可恥吧。 有咖啡卵酪,有音樂幌蚊。 清醒與酒醉, 一線之間...
    fxfx143閱讀 212評論 0 0