刚刚了解属性动画,尝试着写了一个可折叠布局,正好也是项目中用到的。
先上效果图:
layout代码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.mycom.foldpanel.FoldPanelLayout
android:id="@+id/pl_week"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
<TextView
android:id="@+id/tv_week"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:padding="10dp"
android:text="一周内"
android:textSize="15sp" />
<ListView
android:id="@+id/lv_week"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_below="@id/tv_week"
android:background="@android:color/white" />
</com.mycom.foldpanel.FoldPanelLayout>
<com.mycom.foldpanel.FoldPanelLayout
android:id="@+id/pl_yestoday"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@id/pl_week" >
<TextView
android:id="@+id/tv_yestoday"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:padding="10dp"
android:text="昨日"
android:textSize="15sp" />
<ListView
android:id="@+id/lv_yestoday"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_below="@id/tv_yestoday"
android:background="@android:color/white" />
</com.mycom.foldpanel.FoldPanelLayout>
<com.mycom.foldpanel.FoldPanelLayout
android:id="@+id/pl_today"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@id/pl_yestoday"
android:layout_alignParentTop="true" >
<TextView
android:id="@+id/tv_today"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="@android:color/darker_gray"
android:padding="10dp"
android:text="今日"
android:textSize="15sp" />
<ListView
android:id="@+id/lv_today"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@id/tv_today"
android:background="@android:color/white" />
</com.mycom.foldpanel.FoldPanelLayout>
</RelativeLayout>
使用了一个自定义布局,很简单,就是指明了需要改变的属性,本例中既是布局的高度
public class FoldPanelLayout extends RelativeLayout {
public FoldPanelLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
private void setPanelHeight(int panelHeight) {
getLayoutParams().height = panelHeight;
requestLayout();
}
private int getPanelHeight(){
return getLayoutParams().height;
}
}
Activity代码
public class MainActivity extends Activity implements OnClickListener {
private TextView tvToday, tvYestoday, tvWeek;
private ListView lvToday, lvYestoday, lvWeek;
private RelativeLayout rlContainer;
private FoldPanelLayout plToday, plYestoday, plWeek;
//指明已打开的布局
private int expandFlag = EXPAND_TODAY;
private static final int EXPAND_TODAY = R.id.tv_today;
private static final int EXPAND_YESTODAY = R.id.tv_yestoday;
private static final int EXPAND_WEEK = R.id.tv_week;
private String[] TOADYS = new String[20];
private String[] YESTODAYS = new String[20];
private String[] WEEKS = new String[20];
//动画时间
private static final int ANIM_DURATION = 300;
//要改变的属性,名称要与FoldPanelLayout中的set和get方法对应
private static final String ANIM_PROPERTY = "panelHeight";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
initViews();
setData();
}
private void initViews(){
rlContainer = (RelativeLayout) findViewById(R.id.layout_container);
tvToday = (TextView) findViewById(R.id.tv_today);
tvYestoday = (TextView) findViewById(R.id.tv_yestoday);
tvWeek = (TextView) findViewById(R.id.tv_week);
lvToday = (ListView) findViewById(R.id.lv_today);
lvYestoday = (ListView) findViewById(R.id.lv_yestoday);
lvWeek = (ListView) findViewById(R.id.lv_week);
plToday = (FoldPanelLayout) findViewById(R.id.pl_today);
plYestoday = (FoldPanelLayout) findViewById(R.id.pl_yestoday);
plWeek = (FoldPanelLayout) findViewById(R.id.pl_week);
tvToday.setOnClickListener(this);
tvYestoday.setOnClickListener(this);
tvWeek.setOnClickListener(this);
}
private void setData(){
for (int i = 0; i < TOADYS.length; i++) {
TOADYS[i] = "TODAY " + i;
}
lvToday.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, TOADYS));
for (int i = 0; i < YESTODAYS.length; i++) {
YESTODAYS[i] = "YESTODAY " + i;
}
lvYestoday.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, YESTODAYS));
for (int i = 0; i < WEEKS.length; i++) {
WEEKS[i] = "WEEK " + i;
}
lvWeek.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, WEEKS));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_today:
case R.id.tv_yestoday:
case R.id.tv_week:
if (expandFlag != v.getId()) {
expandLayout(v.getId());
collapseLayout(expandFlag);
expandFlag = v.getId();
}
break;
}
}
/**
* 折叠
* @param expandFlag
*/
private void collapseLayout(int expandFlag) {
startAnimation(expandFlag,
rlContainer.getHeight() - tvToday.getHeight() * 2,
tvToday.getHeight());
}
/**
* 展开
* @param expandFlag
*/
private void expandLayout(int expandFlag) {
startAnimation(expandFlag, tvToday.getHeight(), rlContainer.getHeight()
- tvToday.getHeight() * 2);
}
private class AnimUpdateListener implements AnimatorUpdateListener {
ViewGroup vp;
public AnimUpdateListener(ViewGroup vp) {
this.vp = vp;
}
@Override
public void onAnimationUpdate(ValueAnimator arg0) {
vp.getChildAt(1).getLayoutParams().height = (Integer) arg0
.getAnimatedValue();
}
}
private void startAnimation(int expandFlag, int start, int end) {
ViewGroup expandVp = null;
switch (expandFlag) {
case EXPAND_TODAY:
expandVp = plToday;
break;
case EXPAND_YESTODAY:
expandVp = plYestoday;
break;
case EXPAND_WEEK:
expandVp = plWeek;
break;
}
ObjectAnimator anim = ObjectAnimator.ofInt(expandVp, ANIM_PROPERTY,
start, end);
anim.setDuration(ANIM_DURATION);
anim.start();
if (end > start) {// 如果是展开,则需要改变列表的高度
anim.addUpdateListener(new AnimUpdateListener(expandVp));
}
}
}
算是初步实现效果,不过还是觉得这样写的话在Activity中的代码有点多了,应该放在自定义布局里面,再定义展开和折叠的监听接口在Activity里面调用。