超详细源码分析,详解所用特效是如何实现的

cardsui-for-android的下载地址https://github.com/Androguide/cardsui-for-android

以下是我截取的2个图片,可以自定义成Card形式的View,布局可以自己设定。点击露出来的部分可以使点击的Card滑落到下面,也可以左右滑动删除Card。效果非常好

这篇文章主要写下通过源码分析一下几个地方是怎么实现的。

Card的View和布局

相互叠层的card

点击翻转下滑

左右移动删除条目

可以根据需求自行决定观看,哈哈

从git下载导入项目中后,一共有3个文件,一个是Library文件,另外两个是作者写的Demo,第一个很简单,第二个demo是可以用调色板动态创建Card,所以需要另外下载ColorPicker和actionbarsherlock开源项目。

这篇文章只分析源码,所以就不看Demo了,只需要看Library文件就行,下面正式开始:

CardsUILib文件截图

如图一共只有3个包,10多个类。

这里我们只关心这几个类Card, CardStack, StackAdapter, SwipDismissTouchListener, CardUI,下面我们来一个一个分析

定义Card的view和布局详解:

Card

该类是一个抽象类并且继承至AbstractCard抽象类,会重写该抽象类的getView方法,请看我加的中文注解

@Overridepublic View getView(Context context) {//getCardLayout(),这个方法返回一个布局,该布局只有一个FrameLayout,可以理解这句就是创建一个干净的空布局View view = LayoutInflater.from(context).inflate(getCardLayout(), null);mCardLayout = view;try {//这个是通过getCardContent()方法获取View加到之前的空布局上//getCardContent()方法是一个抽象类,具体由子类实现,其实就是为了把子类的View加到父View的布局上((FrameLayout) view.findViewById(R.id.cardContent)).addView(getCardContent(context));} catch (NullPointerException e) {e.printStackTrace();}//为这个布局设置宽高,和Margin,最后返回这个布局,这个布局就是Card的根View了,具体的‘长相’就看子类的实现啦LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);int bottom = Utils.convertDpToPixelInt(context, 12);lp.setMargins(0, 0, 0, bottom);view.setLayoutParams(lp);return view;}Card类就是未来我们自定义Card类的父类,里面定义了一些规范当然他也从AbstractCard中继承了一些规范。

Card类里还有一些其他的方法,比如设置了setOnClickListener(),getOnLongClickListener() 还有一个重要的接口OnCardSwiped 里面有个onCardSwiped方法,这些都是让自定义子类去看需求来实现的,过多的细节就不啰嗦

CardStack

该类的作用看名字就可以猜到,他是一个Card堆,或者说是Card的一个集合,专门存放Card。

讲到这里,需要跳一下,暂时把这个类放下先去看另一个类CardUI。一会回来再接着看他

CardUI

该类继承自FrameLayout。哈哈,说到这里大家是不是已经知道怎么回事了。

没错,CardUI, CardStack, Card这3个类是一一包含的关系。CardStack装入各种Card,最后再把他放到最终父布局CardUI中。

我截个图大家理解更清晰

整个所有是一个CardUI

所以CardUI中一定有addCard方法 和addStack方法

public void addCard(Card card, boolean refresh) {CardStack stack = new CardStack();stack.add(card);mStacks.add(stack);if (refresh)refresh();}public void addStack(CardStack stack, boolean refresh) {mStacks.add(stack);if (refresh)refresh();}每次add之后都会调用一下refresh()方法,原因当然就是要重新来调整布局的大小啦

看refresh方法前先看一下这个类初始化的一些代码

//该方法在构造方法中调用,目的就是初始化该自定义布局用到的private void initData(Context context) {mContext = context;LayoutInflater inflater = LayoutInflater.from(context);//所有CardStack的集合mStacks = new ArrayList<AbstractCard>();//inflate a different layout, depending on the number of columns//自定义一个listview作为容器if (mColumnNumber == 1) {inflater.inflate(R.layout.cards_view, this);// init observable scrollviewmListView = (QuickReturnListView) findViewById(R.id.listView);} else {//initialize the mulitcolumn view//使用TableLayout作为容器,其原理和使用listview基本相同,不过效果没有listview好,所以基本不用它inflater.inflate(R.layout.cards_view_multicolumn, this);mTableLayout = (TableLayout) findViewById(R.id.tableLayout);}// mListView.setCallbacks(this);mHeader = inflater.inflate(R.layout.header, null);mQuickReturnView = (ViewGroup) findViewById(R.id.sticky);mPlaceholderView = mHeader.findViewById(R.id.placeholder);}耿耿于怀着过去和忐忑不安着未来的人,也常常挥霍无度着现在。

超详细源码分析,详解所用特效是如何实现的

相关文章:

你感兴趣的文章:

标签云: