eclipse 如何在 Android 中的 ListView 中使单元格在触摸时垂直展开和收缩?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12522348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I make a cell in a ListView in Android expand and contract vertically when it's touched?
提问by Ethan Allen
I have a cell in a ListView that has a bunch of text in it. I show the first two rows of text and then end it with a "..." if it goes beyond. I want a user to be able to touch the cell and have it expand dynamically within the view, displaying all of the data. Then when they touch the cell again, it contracts back to it's normal size.
我在 ListView 中有一个单元格,里面有一堆文本。我显示前两行文本,如果超出,则以“...”结尾。我希望用户能够触摸单元格并让它在视图中动态扩展,显示所有数据。然后当他们再次接触细胞时,它会收缩回正常大小。
I've seen an iOS app do this and it's very cool. Is there any way to do this with Android? How?
我见过一个 iOS 应用程序这样做,它非常酷。有没有办法用Android做到这一点?如何?
回答by Leonardo Cardoso
I've implemented a simple code that works in all Android's sdk versions.
我已经实现了一个适用于所有 Android sdk 版本的简单代码。
See below its working and the code.
请参阅下面的工作和代码。
Github code: https://github.com/LeonardoCardoso/Animated-Expanding-ListView
Github 代码:https: //github.com/LeonardoCardoso/Animated-Expanding-ListView
For information on my website: http://android.leocardz.com/animated-expanding-listview/
有关我的网站的信息:http: //android.leocardz.com/animated-expanding-listview/
Basically, you have to create a custom TranslateAnimation and a Custom List Adapter and, while it's animating, you have to update the current height of listview item and notify the adapter about this change.
基本上,您必须创建一个自定义 TranslateAnimation 和一个自定义列表适配器,并且在进行动画处理时,您必须更新列表视图项的当前高度并将此更改通知适配器。
Let's go to the code.
让我们来看看代码。
List Item layout
<?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>
Activity Layout
<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>
List Item class
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; } }
View Holder class
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; } }
Custom Animation class
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(); } }
Custom List Adapter class
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; } }
Main Activity
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)); } }
列表项布局
<?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; } }
查看持有人类
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)); } }
回答by Nam Trung
Here is example from Udinic. It had listview item expand with animation and require API level only 4+
这是来自 Udinic 的例子。它具有带动画的列表视图项扩展,并且只需要 API 级别 4+
in onItemClick event use ExpandAnimation
在 onItemClick 事件中使用 ExpandAnimation
/**
* This animation class is animating the expanding and reducing the size of a view.
* The animation toggles between the Expand and Reduce, depending on the current state of the view
* @author Udinic
*
*/
public class ExpandAnimation extends Animation {
private View mAnimatedView;
private LayoutParams mViewLayoutParams;
private int mMarginStart, mMarginEnd;
private boolean mIsVisibleAfter = false;
private boolean mWasEndedAlready = false;
/**
* Initialize the animation
* @param view The layout we want to animate
* @param duration The duration of the animation, in ms
*/
public ExpandAnimation(View view, int duration) {
setDuration(duration);
mAnimatedView = view;
mViewLayoutParams = (LayoutParams) view.getLayoutParams();
// decide to show or hide the view
mIsVisibleAfter = (view.getVisibility() == View.VISIBLE);
mMarginStart = mViewLayoutParams.bottomMargin;
mMarginEnd = (mMarginStart == 0 ? (0- view.getHeight()) : 0);
view.setVisibility(View.VISIBLE);
}
@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();
// Making sure we didn't run the ending before (it happens!)
} else if (!mWasEndedAlready) {
mViewLayoutParams.bottomMargin = mMarginEnd;
mAnimatedView.requestLayout();
if (mIsVisibleAfter) {
mAnimatedView.setVisibility(View.GONE);
}
mWasEndedAlready = true;
}
}
}
Detail usage is in project.
详细用法在项目中。
回答by Leandros
There is a sample in the SDK, it could help you.
SDK 中有一个示例,它可以帮助您。
It's called, obviously, ExpandableList
. Located in the API Demos (/docs/resources/samples/ApiDemos/src/com/example/android/apis/view)
显然,它被称为,ExpandableList
。位于 API Demos (/docs/resources/samples/ApiDemos/src/com/example/android/apis/view)
回答by ahodder
Here is an option that I would do:
这是我会做的一个选项:
Add an if statement to your ListView's BaseAdapter that will query your ListView for current selected items. If the current item you are drawing (in your BaseAdapter) is the selected item's position, then create your expanded view instead. Then resume normal view creation.
向 ListView 的 BaseAdapter 添加一个 if 语句,该语句将查询您的 ListView 以获取当前选定的项目。如果您正在绘制的当前项目(在您的 BaseAdapter 中)是所选项目的位置,则改为创建您的扩展视图。然后恢复正常的视图创建。
Edit:
编辑:
I made this as an option under the assumption that you want to expand one (1) item at a time and not, say, an entire list.
在假设您希望一次扩展一 (1) 个项目而不是整个列表的情况下,我将此作为一个选项。
回答by caiocpricci2
I've never used ExpandableListViews, but I figure it's pretty simple to do a "manual" implementation of that. Extending an ArrayAdapter we can manipulate the row layout as we want. So, create your extended adapter, and two onClickListeners, one to expand, one to contract. I've pasted the whole class here.
我从未使用过 ExpandableListViews,但我认为对其进行“手动”实现非常简单。扩展 ArrayAdapter 我们可以根据需要操作行布局。因此,创建您的扩展适配器和两个 onClickListener,一个用于扩展,一个用于收缩。我把整个班级都贴在这里了。
If you don't want some of the items to be extendable just adjust the listeners to your needs. If you want it to look better you can add some sliding animation, but from here you should have enough to do whatever you need!
如果您不希望某些项目可扩展,只需根据您的需要调整侦听器。如果你想让它看起来更好,你可以添加一些滑动动画,但从这里你应该有足够的东西来做你需要的!
public class ExtendedAdapter extends BaseAdapter {
public static final String TAG = "TodoAdapter";
private Context mContext;
private int layoutResource;
private List<String> items;
private OnClickListener expand;
private OnClickListener contract;
public ExtendedAdapter(Context context, int textViewResourceId,
List<String> items) {
this.items = items;
this.mContext = context;
this.layoutResource = textViewResourceId;
expand = new OnClickListener() {
@Override
public void onClick(View v) {
TextView tv = (TextView) v;
String[] textSplited = tv.getText().toString().split(" "); // somehow split your text
tv.setMaxLines(textSplited.length);
StringBuilder sb = new StringBuilder();
for (String word : textSplited)
sb.append(word + "\n");
tv.setText(sb.toString());
tv.setOnClickListener(contract);
}
};
contract = new OnClickListener() {
@Override
public void onClick(View v) {
TextView tv = (TextView) v;
tv.setMaxLines(1);
String[] textSplitted = tv.getText().toString().split("\n");
StringBuilder sb = new StringBuilder();
for (String word : textSplitted)
sb.append(word + " ");
tv.setText(sb.toString());
tv.setOnClickListener(expand);
}
};
}
public int getCount() {
return items.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(layoutResource, null);
}
TextView text = (TextView) v.findViewById(R.id.extended_text);
text.setText(items.get(position));
text.setOnClickListener(expand);
return v;
}
}
And the row_layout.xml
和 row_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingTop="4dip"
android:paddingBottom="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:textSize="13sp">
<TextView android:id="@+id/extended_text"
android:layout_width="275dip"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"/>
</LinearLayout>
回答by you786
What you want to do is have a flag that knows if the row is expanded or not. If it is, then run an animationthat shrinks it, and vice versa.
您想要做的是有一个标志,该标志知道该行是否已展开。如果是,则运行一个缩小它的动画,反之亦然。
public void onListItemClicked(int position)
{
View v = listView.getView(position);
if(expanded[position])
v.startAnimation(shrinkAnimation);
else
v.startAnimation(growAnimation);
expanded[position] = !expanded[position];
}
Simple.
简单的。
Howeverif what you are doing is something similar to the screen shot you implemented, I would advise against doing this with a ListView. The views are each different enough to warrant just doing this manually with LinearLayouts
. Only use the ListView if the number of rows is unknown or very large.
但是,如果您正在执行的操作与您实现的屏幕截图类似,我建议不要使用 ListView 执行此操作。每个视图都足够不同,因此只需使用LinearLayouts
. 仅当行数未知或非常大时才使用 ListView。