【问题标题】:Android Activity Transition in a ListViewListView 中的 Android Activity 转换
【发布时间】: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)从那里正常地为比例设置动画。

标签: java android listview animation transition


【解决方案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 是非常困难的。我建议你采用这种方法。我已经包含了一个完整的工作示例。

    1. 将您的 ListView 视图放在 relativeLayout 中
    2. OnClick,为您的渲染器添加一个副本
    3. 查找渲染器相对于 ListView 父级的位置的全局坐标
    4. 将复制的渲染器添加到RelativeLayout(ListView的父级)
    5. 为 listView 制作动画
    6. 在该动画结束时,为您的新渲染器制作动画
    7. 利润!
    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。

    详情

    1. setAdapter(Adapter adapter) 方法中为您的 AdapterView 设置适配器。

    2. 重写 onLayout 方法以将项目添加到您的 AdapterView。您必须测量项目并将其作为子视图添加到列表的正确位置(实际上是您的 AdapterView)。

    3. 覆盖onTouchEvent(),这样你的列表就可以滚动了列表,当用户从屏幕上拿起他/她的手指时,您必须决定其他项目是否可见或必须扩展所选项目。

    示例

    Making your own 3D list(以及那篇文章的第 2 部分)很好地演示了我为您展示的内容。其目的是创建 3D 列表。您可以查看更多详细信息、sn-p 代码和完整代码。虽然您有将其更改为 onTouchEvent() 以达到您想要的效果。

    注意您甚至可以在 API1 中执行此操作

    希望对你有帮助!

    【讨论】:

    • 真的很有趣。我会看看这种方法。
    • 很好的资源,但不要像“制作自己的 3d 列表”那样在 onTouch MotionEvent.ACTION_MOVE 的 AdapterView 中执行 requestLayout。这是非常低效的。
    【解决方案4】:

    在您的 xml 文件中,在 ListView 下方,采用另一个线性布局/相对布局并根据您的需要进行设计,但要确保它的可见性必须消失。当您点击列表视图项时,用您的内容填充它并长按完成所有操作。对于动画,将其向左缩放。

    【讨论】:

      【解决方案5】:

      当你按下该列表元素时,它应该调用动画,你必须通过动画。在那个动画中你应该设计它,如果你使用图像,在那些动画中意味着通过 9 个补丁图像

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-02
        • 1970-01-01
        相关资源
        最近更新 更多