我有一個ListView
。最初,ListView
包含一些數據。當用戶點擊一個項目時,另一個佈局將被動態添加到該項目,因此它的高度將會增加。展開帶有動畫的ListView項目
現在,當物品的高度增加時,它立即顯示修改後的物品。不過,我想要的是讓它變成動畫,以便逐漸增加項目的高度。
我有一個ListView
。最初,ListView
包含一些數據。當用戶點擊一個項目時,另一個佈局將被動態添加到該項目,因此它的高度將會增加。展開帶有動畫的ListView項目
現在,當物品的高度增加時,它立即顯示修改後的物品。不過,我想要的是讓它變成動畫,以便逐漸增加項目的高度。
我想我一直在尋找相同的問題,我正在尋找一種方法來動畫擴展的ListView項目,因爲一些新的內容顯示(我只是將一些視圖的可見性從GONE
更改爲VISIBLE
)。我已經通過mirroredAbstraction
使用的答案,幫我申請一個翻譯的動畫(我不想一個旋轉的動畫):
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator"
android:fromYDelta="0"
android:toYDelta="-100%p"
android:duration="500"
/>
每個的意見。它創造了一個不錯的效果,但仔細觀察,listview項目實際上突然擴展到需要的整個大小,然後動畫將視圖放到了位置。但是我想要的是隨着視圖進入可見性,列表視圖項目的效果不斷增長。
我發現正是我一直在尋找在這裏: expanding-listview-items
的博客有一個鏈接到自己的github上的樣品,在這裏: ExpandAnimationExample
如果你發現這些網站去了,請告訴我,我將使我的副本可用。
他把陰性切緣上的內容接觸到的知名度以及設置能見度GONE
:
android:layout_marginBottom="-50dip"
,並寫了一個動畫操縱下邊距:
public class ExpandAnimation extends Animation {
...
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (interpolatedTime < 1.0f) {
// Calculating the new bottom margin, and setting it
mViewLayoutParams.bottomMargin = mMarginStart
+ (int) ((mMarginEnd - mMarginStart) * interpolatedTime);
// Invalidating the layout, making us seeing the changes we made
mAnimatedView.requestLayout();
}
...
}
}
,它看起來非常好。我發現他的答案,這太問題(可能重複):
Adding animation to a ListView in order to expand/collapse content
另外,請讓我知道,如果你知道另一種方式做同樣的事情。
您將必須實現動畫在你ListView
Adapter
達到你想要什麼,
首先創建一個基本的animation.xml
文件,創建res文件夾命名動畫文件夾,然後把你的animation.xml文件它。
例如,我已經創建了一個名爲rotate_animation.xml
<?xml version="1.0" encoding="UTF-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="400" />
樣本動畫然後創建Animation
Object
一個實例這樣
private Animation animation;
然後在你的適配器實現的getView方法做這樣的事情
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolder viewHolder;
if (convertView == null) {
LayoutInflater li = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = li.inflate(R.layout.my_layout, null);
viewHolder = new ViewHolder(v);
v.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) v.getTag();
}
viewHolder.mAppName.setText("SomeText");
viewHolder.mAppImage.setImageDrawable(R.drawable.someImage);
animation = AnimationUtils.loadAnimation(mContext, R.anim.my_animation);
v.startAnimation(animation);
return v;
}
我實現了一個簡單的代碼,在所有Android的SDK版本的作品。
看到它的工作和下面的代碼。
Github的代碼:https://github.com/LeonardoCardoso/Animated-Expanding-ListView
有關我的網站的信息:http://android.leocardz.com/animated-expanding-listview/
基本上,你必須創建一個自定義TranslateAnimation和自定義列表適配器和,而它的動畫,你必須更新列表視圖項目的當前高度並通知適配器有關此更改。
我們去的代碼。
列表項目佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text_wrap"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin" >
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp" >
</TextView>
</LinearLayout>
活動佈局
<RelativeLayout 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=".MainActivity" >
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@android:color/black"
android:dividerHeight="3dp" >
</ListView>
</RelativeLayout>
列表項類
public class ListItem {
private String text;
private int collapsedHeight, currentHeight, expandedHeight;
private boolean isOpen;
private ListViewHolder holder;
private int drawable;
public ListItem(String text, int collapsedHeight, int currentHeight,
int expandedHeight) {
super();
this.text = text;
this.collapsedHeight = collapsedHeight;
this.currentHeight = currentHeight;
this.expandedHeight = expandedHeight;
this.isOpen = false;
this.drawable = R.drawable.down;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getCollapsedHeight() {
return collapsedHeight;
}
public void setCollapsedHeight(int collapsedHeight) {
this.collapsedHeight = collapsedHeight;
}
public int getCurrentHeight() {
return currentHeight;
}
public void setCurrentHeight(int currentHeight) {
this.currentHeight = currentHeight;
}
public int getExpandedHeight() {
return expandedHeight;
}
public void setExpandedHeight(int expandedHeight) {
this.expandedHeight = expandedHeight;
}
public boolean isOpen() {
return isOpen;
}
public void setOpen(boolean isOpen) {
this.isOpen = isOpen;
}
public ListViewHolder getHolder() {
return holder;
}
public void setHolder(ListViewHolder holder) {
this.holder = holder;
}
public int getDrawable() {
return drawable;
}
public void setDrawable(int drawable) {
this.drawable = drawable;
}
}
查看Holder類
public class ListViewHolder {
private LinearLayout textViewWrap;
private TextView textView;
public ListViewHolder(LinearLayout textViewWrap, TextView textView) {
super();
this.textViewWrap = textViewWrap;
this.textView = textView;
}
public TextView getTextView() {
return textView;
}
public void setTextView(TextView textView) {
this.textView = textView;
}
public LinearLayout getTextViewWrap() {
return textViewWrap;
}
public void setTextViewWrap(LinearLayout textViewWrap) {
this.textViewWrap = textViewWrap;
}
}
自定義動畫類
public class ResizeAnimation extends Animation {
private View mView;
private float mToHeight;
private float mFromHeight;
private float mToWidth;
private float mFromWidth;
private ListAdapter mListAdapter;
private ListItem mListItem;
public ResizeAnimation(ListAdapter listAdapter, ListItem listItem,
float fromWidth, float fromHeight, float toWidth, float toHeight) {
mToHeight = toHeight;
mToWidth = toWidth;
mFromHeight = fromHeight;
mFromWidth = fromWidth;
mView = listItem.getHolder().getTextViewWrap();
mListAdapter = listAdapter;
mListItem = listItem;
setDuration(200);
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float height = (mToHeight - mFromHeight) * interpolatedTime
+ mFromHeight;
float width = (mToWidth - mFromWidth) * interpolatedTime + mFromWidth;
LayoutParams p = (LayoutParams) mView.getLayoutParams();
p.height = (int) height;
p.width = (int) width;
mListItem.setCurrentHeight(p.height);
mListAdapter.notifyDataSetChanged();
}
}
自定義列表適配器類
public class ListAdapter extends ArrayAdapter<ListItem> {
private ArrayList<ListItem> listItems;
private Context context;
public ListAdapter(Context context, int textViewResourceId,
ArrayList<ListItem> listItems) {
super(context, textViewResourceId, listItems);
this.listItems = listItems;
this.context = context;
}
@Override
@SuppressWarnings("deprecation")
public View getView(int position, View convertView, ViewGroup parent) {
ListViewHolder holder = null;
ListItem listItem = listItems.get(position);
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.list_item, null);
LinearLayout textViewWrap = (LinearLayout) convertView
.findViewById(R.id.text_wrap);
TextView text = (TextView) convertView.findViewById(R.id.text);
holder = new ListViewHolder(textViewWrap, text);
} else
holder = (ListViewHolder) convertView.getTag();
holder.getTextView().setText(listItem.getText());
LayoutParams layoutParams = new LayoutParams(LayoutParams.FILL_PARENT,
listItem.getCurrentHeight());
holder.getTextViewWrap().setLayoutParams(layoutParams);
holder.getTextView().setCompoundDrawablesWithIntrinsicBounds(
listItem.getDrawable(), 0, 0, 0);
convertView.setTag(holder);
listItem.setHolder(holder);
return convertView;
}
}
主要活動
public class MainActivity extends Activity {
private ListView listView;
private ArrayList<ListItem> listItems;
private ListAdapter adapter;
private final int COLLAPSED_HEIGHT_1 = 150, COLLAPSED_HEIGHT_2 = 200,
COLLAPSED_HEIGHT_3 = 250;
private final int EXPANDED_HEIGHT_1 = 250, EXPANDED_HEIGHT_2 = 300,
EXPANDED_HEIGHT_3 = 350, EXPANDED_HEIGHT_4 = 400;
private boolean accordion = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list);
listItems = new ArrayList<ListItem>();
mockItems();
adapter = new ListAdapter(this, R.layout.list_item, listItems);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
toggle(view, position);
}
});
}
private void toggle(View view, final int position) {
ListItem listItem = listItems.get(position);
listItem.getHolder().setTextViewWrap((LinearLayout) view);
int fromHeight = 0;
int toHeight = 0;
if (listItem.isOpen()) {
fromHeight = listItem.getExpandedHeight();
toHeight = listItem.getCollapsedHeight();
} else {
fromHeight = listItem.getCollapsedHeight();
toHeight = listItem.getExpandedHeight();
// This closes all item before the selected one opens
if (accordion) {
closeAll();
}
}
toggleAnimation(listItem, position, fromHeight, toHeight, true);
}
private void closeAll() {
int i = 0;
for (ListItem listItem : listItems) {
if (listItem.isOpen()) {
toggleAnimation(listItem, i, listItem.getExpandedHeight(),
listItem.getCollapsedHeight(), false);
}
i++;
}
}
private void toggleAnimation(final ListItem listItem, final int position,
final int fromHeight, final int toHeight, final boolean goToItem) {
ResizeAnimation resizeAnimation = new ResizeAnimation(adapter,
listItem, 0, fromHeight, 0, toHeight);
resizeAnimation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
listItem.setOpen(!listItem.isOpen());
listItem.setDrawable(listItem.isOpen() ? R.drawable.up
: R.drawable.down);
listItem.setCurrentHeight(toHeight);
adapter.notifyDataSetChanged();
if (goToItem)
goToItem(position);
}
});
listItem.getHolder().getTextViewWrap().startAnimation(resizeAnimation);
}
private void goToItem(final int position) {
listView.post(new Runnable() {
@Override
public void run() {
try {
listView.smoothScrollToPosition(position);
} catch (Exception e) {
listView.setSelection(position);
}
}
});
}
private void mockItems() {
listItems
.add(new ListItem(
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
COLLAPSED_HEIGHT_1, COLLAPSED_HEIGHT_1,
EXPANDED_HEIGHT_1));
listItems
.add(new ListItem(
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
COLLAPSED_HEIGHT_2, COLLAPSED_HEIGHT_2,
EXPANDED_HEIGHT_2));
listItems
.add(new ListItem(
"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
COLLAPSED_HEIGHT_3, COLLAPSED_HEIGHT_3,
EXPANDED_HEIGHT_3));
listItems
.add(new ListItem(
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.",
COLLAPSED_HEIGHT_2, COLLAPSED_HEIGHT_2,
EXPANDED_HEIGHT_4));
listItems
.add(new ListItem(
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga.",
COLLAPSED_HEIGHT_1, COLLAPSED_HEIGHT_1,
EXPANDED_HEIGHT_4));
listItems
.add(new ListItem(
"Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.",
COLLAPSED_HEIGHT_2, COLLAPSED_HEIGHT_2,
EXPANDED_HEIGHT_4));
listItems
.add(new ListItem(
"Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae.",
COLLAPSED_HEIGHT_3, COLLAPSED_HEIGHT_3,
EXPANDED_HEIGHT_3));
listItems
.add(new ListItem(
"Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.",
COLLAPSED_HEIGHT_1, COLLAPSED_HEIGHT_1,
EXPANDED_HEIGHT_4));
}
}
這段代碼的表現如何?看到它如此頻繁地通知,處理複雜視圖似乎相當沉重...... – Pkmmte
確實。但是AFAIK在沒有經常通知的情況下,如果你在動畫的時候滾動它,listview就會自行消失。 –
使用值動畫解決方案看起來不錯:
ValueAnimator animator = ValueAnimator.ofInt(100, 300);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
listViewItem.getLayoutParams().height = (Integer) animation.getAnimatedValue();
listViewItem.requestLayout();
}
});
animator.start();
剛剛看過的Android開發者指南,這是值得一讀:http://developer.android.com/guide/topics/graphics/prop-animation.html
但請記住,這requestLayout()處理是沉重的。由於requestLayout的一個()調用盡一切附近的元素,這是視覺上的影響,重新計算它的佈局。這可能是更好的使用負下邊距(隱藏在另一個的元素的某些部分),並使用以下方法來顯示它:
listViewItem.setTranslationY((Integer) animation.getAnimatedValue());
當然,你可以動畫只是底部邊緣,置身於另一個建議回答這個問題。
我的使用情況是隻是爲了顯示有或多或少的文字。所以從2-6最大線例如一個能做到這一點切換列表視圖項的狀態。它也是動畫。動畫不看起來一模一樣,但...
if(!textDescriptionLenghtToggle) { // simple boolean toggle
ObjectAnimator animation = ObjectAnimator.ofInt(
textViewContainingDescription,
"maxLines",
6);
animation.setDuration(300);
animation.start();
} else {
ObjectAnimator animation = ObjectAnimator.ofInt(
textViewContainingDescription,
"maxLines",
2);
animation.setDuration(300);
animation.start();
}
在這種情況下,ListView項目的高度是事先已知的。但是,就我而言,這是動態的。我的意思是,擴展布局的高度將在運行時知道。 – Manjunath
是的,我明白了......我想我可能需要能夠對動態添加/創建的內容產生這種效果。所以,我也在尋找。我想提高你的問題,讓更多的人看到它,但是你並沒有太詳細(即你沒有看到動態的部分!),至少你應該改述這個令人困惑的陳述:「所以,現在是什麼我想要的是:當物品的高度增加時,它會突然顯示修改過的物品,但是我需要在它增加物品高度時進行動畫處理。「 – David