ListView 中的 Android Activity 转换
Posted
技术标签:
【中文标题】ListView 中的 Android Activity 转换【英文标题】:Android Activity Transition in a ListView 【发布时间】:2013-01-12 20:09:07 【问题描述】:我正在尝试在 android 中完成以下 Activity 转换:
在1中我们看到了一个普通的ListView。现在 (2),当我将手指放在 ListView 元素上并向左滑动手指时,所有其他 ListView 元素都会移开,但我的手指放在上面的元素除外。如果转换完成,“选定”的 ListView 元素会在屏幕上展开并显示一些内容。
问题:这种转换是否可以通过现有的 API 函数实现?
【问题讨论】:
Element里面有什么?展开高度是多少?你打算怎么把它倒回去? 我不知道这是否可能,也许你可以通过自定义这个库来实现这个github.com/bauerca/drag-sort-listview @Leonidos (3) 中的展开更像是动画。返回时(例如通过触摸后退箭头),您会看到 (1) 中的列表。在 (3) 中,我只需要一个动画,提示您选择的 ListView 元素的内容已显示。 我正在处理此问题,但没有时间继续:请查看github.com/sherifelkhatib/AnimationFactory 您是否尝试过使用以下组合:1)将视图复制到位图中(或制作它的辅助实例),2)在 listList 中的所有其他子项(或整个 listView原始设置为不可见)。 3) 完成后,将复制的视图添加到 listView 的父级列表中的全局位置。 4)从那里正常地为比例设置动画。 【参考方案1】:如果你的目标是 JellyBean 或以上,你可以使用 ActivityOptions 类来自定义活动启动动画。
以下是实现此目的的伪代码:
Intent i = //the intent for the new activity
View v = //the selected list item
Bundle bundle = ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getWidth(), v.getHeight()).toBundle();
startActivity(i, bundle);
【讨论】:
【参考方案2】:虽然@hasanghaforian 在技术上是正确的,但是继承 AdapterView 是非常困难的。我建议你采用这种方法。我已经包含了一个完整的工作示例。
-
将您的 ListView 视图放在 relativeLayout 中
OnClick,为您的渲染器添加一个副本
查找渲染器相对于 ListView 父级的位置的全局坐标
将复制的渲染器添加到RelativeLayout(ListView的父级)
为 listView 制作动画
在该动画结束时,为您的新渲染器制作动画
利润!
public class MainActivity extends Activity
private RelativeLayout layout;
private ListView listView;
private MyRenderer selectedRenderer;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
layout = new RelativeLayout(this);
setContentView(layout);
listView = new ListView(this);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
layout.addView(listView, rlp);
listView.setAdapter(new MyAdapter());
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
// find out where the clicked view sits in relationship to the
// parent container
int t = view.getTop() + listView.getTop();
int l = view.getLeft() + listView.getLeft();
// create a copy of the listview and add it to the parent
// container
// at the same location it was in the listview
selectedRenderer = new MyRenderer(view.getContext());
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(view.getWidth(), view
.getHeight());
rlp.topMargin = t;
rlp.leftMargin = l;
selectedRenderer.textView.setText(((MyRenderer) view).textView.getText());
layout.addView(selectedRenderer, rlp);
view.setVisibility(View.INVISIBLE);
// animate out the listView
Animation outAni = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, -1f, Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, 0f);
outAni.setDuration(1000);
outAni.setFillAfter(true);
outAni.setAnimationListener(new Animation.AnimationListener()
@Override
public void onAnimationStart(Animation animation)
@Override
public void onAnimationRepeat(Animation animation)
@Override
public void onAnimationEnd(Animation animation)
ScaleAnimation scaleAni = new ScaleAnimation(1f,
1f, 1f, 2f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
scaleAni.setDuration(400);
scaleAni.setFillAfter(true);
selectedRenderer.startAnimation(scaleAni);
);
listView.startAnimation(outAni);
);
public class MyAdapter extends BaseAdapter
@Override
public int getCount()
return 10;
@Override
public String getItem(int position)
return "Hello World " + position;
@Override
public long getItemId(int position)
return position;
@Override
public View getView(int position, View convertView, ViewGroup parent)
MyRenderer renderer;
if (convertView != null)
renderer = (MyRenderer) convertView;
else
renderer = new MyRenderer(MainActivity.this);
renderer.textView.setText(getItem(position));
return renderer;
public class MyRenderer extends RelativeLayout
public TextView textView;
public MyRenderer(Context context)
super(context);
setPadding(20, 20, 20, 20);
setBackgroundColor(0xFFFF0000);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
rlp.addRule(CENTER_IN_PARENT);
textView = new TextView(context);
addView(textView, rlp);
【讨论】:
太棒了,比我预期的要少得多。在测试之后,我看到动画效果很好,但是在动画之后,如果我点击屏幕,列表就会显示出来,并且复制渲染不会从父布局中删除。我也想让它在不同的方向上工作(那真的很棒:D) 这是一个概念证明。根据您自己的需要实施它【参考方案3】:标准ListView
的一个缺点是缺乏良好的物理特性(以及改变它的能力)。因此,如果你想改变它,你只需要实现你自己的视图。你必须扩展一个ViewGroup
的子类,即AdapterView
,这样AdapterView就会成为你的半List。
详情:
在 setAdapter(Adapter adapter)
方法中为您的 AdapterView 设置适配器。
重写 onLayout
方法以将项目添加到您的 AdapterView
。您必须测量项目并将其作为子视图添加到列表的正确位置(实际上是您的 AdapterView)。
示例:
Making your own 3D list(以及那篇文章的第 2 部分)很好地演示了我为您展示的内容。其目的是创建 3D 列表。您可以查看更多详细信息、sn-p 代码和完整代码。虽然您有将其更改为 onTouchEvent()
以达到您想要的效果。
注意:您甚至可以在 API1 中执行此操作。
希望对你有帮助!
【讨论】:
真的很有趣。我会看看这种方法。 很好的资源,但不要像“制作自己的 3d 列表”那样在 onTouch MotionEvent.ACTION_MOVE 的 AdapterView 中执行 requestLayout。这是非常低效的。【参考方案4】:在您的 xml 文件中,在 ListView 下方,采用另一个线性布局/相对布局并根据您的需要进行设计,但要确保它的可见性必须消失。当您点击列表视图项时,用您的内容填充它并长按完成所有操作。对于动画,将其向左缩放。
【讨论】:
【参考方案5】:当你按下该列表元素时,它应该调用动画,你必须通过动画。在那个动画中你应该设计它,如果你使用图像,在那些动画中意味着通过 9 个补丁图像
【讨论】:
以上是关于ListView 中的 Android Activity 转换的主要内容,如果未能解决你的问题,请参考以下文章
ListView 中的 Android Activity 转换