涉及技术

ListView使用、动画、自定义控件

第一步:ListView

ListView应该是每个学习Android的人都会学到的,所以我在这也就不仔细的说了,我只说一下设计的细节。
我们需要建立一个布局,用来显示在上一篇文章的PagerActivity中。xml不贴出了,可以看这里。其实很简单,就是建立了一个ListView,设置分割距离和颜色并且去掉上下的阴影。ListView中每个item显示的布局可以看这里,就只是一个TextView,用于显示标题。
关于数据我觉得我也不用多说,xml的处理也是Android学习的必学课程,为了练习xml的处理,所以我处理数据用了不同的方法,这里用的是SAX。数据提取出来之后给item加上点击事件:跳转到我们还未创建的HonorActivity。HonorActivity是用来显示每个荣誉的详细信息,也就是三个TextView,很简单,代码和布局可以看这里这里。代码大概如下:
            honorsListView = (ListView) honors.findViewById(R.id.honors_list);
            honorsListView.setAdapter(new ArrayAdapter(this, R.layout.honors_item, honorsListData()));
            honorsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView parent, View view,final int position, long id) {
                            Intent toHonor = new Intent(context, HonorActivity.class);
                            toHonor.putExtra("id", position + 1);
                            startActivity(toHonor);
                }
            });
但是简简单单的展示这些文字,完全没有一点吸引力,有吸引力的界面都是有动态交互的,所以我决定给这个列表的交互加一些动画,效果如下:
这有两个动画,第一个是点击了某一个条目之后和返回条目列表的动画,第二个是Activity切换的动画。
先说第二个动画,这个动画比较简单,我是基于主题来实现的,在Android中,AndroidManifest.xml文件中对Activity指定android:theme属性就可以设置主题了,如下:

然后再定义这个主题:

    

这个主题只有一个item,就是android:windowAnimationStyle,顾名思义,这个属性指定了窗口动画的样式,这个样式也是我们自己创建的,如下:

    

关于这个样式的四个属性大家看名字也能看的到,也就是新打开的Activity进入退出的动画和旧Activity进入退出的动画,动画的定义由于代码比较多,占篇幅太大,我就不贴出来了,这里有四个链接:

如果觉得有必要解释这些动画的话,我会重新写一篇文章来介绍Android的动画。
现在要实现第一个动画了,因为要达到图片中那样像拉帘子一样的效果,所以我们针对每一个ListView的item都要做处理,思路如下:
1.获取到每个item。
2.为每个item添加一个左右方向压缩的动画。
3.每个动画都延迟一定时间执行。
4.最后一个动画执行完成之后跳转Activity。
思路一出来,代码写起来就很简单了,修改之前的代码后,如下:
            honorsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView parent, View view,final int position, long id) {
                    int count = honorsListView.getChildCount();
                    for (int i = 0; i < count; i++) {
                        View child = honorsListView.getChildAt(i);//获取到item
                        ScaleAnimation sa = new ScaleAnimation(1.0f, 0.0f, 1.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f,
                                Animation.RELATIVE_TO_SELF, 0);//缩放动画,只缩放左右
                        sa.setDuration(500);//动画执行的时间
                        sa.setFillAfter(true);//这个一定要设置,不然动画执行完后item又会变回原来的样子
                        sa.setStartOffset((count - i)*50);//设置开始时间的偏移量,就是靠这个来实现拉帘子的效果
                        if (child != null) {
                            child.setAnimation(sa);//将动画设置给item
                        }
                        child.startAnimation(sa);//执行动画
                    }
                    //因为我们的拉帘子效果是从下面拉到上面,所以最后一个执行的动画是第一个item,给item设置一个
                    //AnimationListener,在onAnimationEnd中完成跳转Activity
                    honorsListView.getChildAt(0).getAnimation().setAnimationListener(new Animation.AnimationListener() {
                        @Override
                        public void onAnimationStart(Animation animation) {
                        }
                        @Override
                        public void onAnimationEnd(Animation animation) {
                            Intent toHonor = new Intent(context, HonorActivity.class);
                            toHonor.putExtra("id", position + 1);
                            startActivity(toHonor);
                        }
                        @Override
                        public void onAnimationRepeat(Animation animation) {
                        }
                    });

                }
            });

第二步:自定义控件

做Android的开发,怎么能不会自定义控件呢,所以为了体现我掌握了这个技术,我专门在简历中自定义了一个图表控件:
通过这个控件,能够展示我对某一个技术的熟练度。自定义控件怎么做我也不详细的说,我们定义一个继承View的类。变量的初始化不是重点,各个变量的意义如下:
重点是继承onDraw来绘制这个控件,思路如下:
1.绘制一个内圆,内填充。
2.绘制一个外扇形,内部不填充,不连接圆心,边调粗一些。
3.绘制技能的名字。
话不多说,有了思路直接就有代码:
    @Override
    protected void onDraw(Canvas canvas) {
//        Log.i("Ring","onDraw");
        super.onDraw(canvas);
        int width = canvas.getClipBounds().width();//获取高度
        int center = width / 2;//计算中心点
        int innerCircle = Math.round(center - this.ringWidth - 4); //设置内圆半径
        int ringWidth = Math.round(this.ringWidth); //设置圆环宽度

        //绘制内圆
        Paint p = new Paint();
        p.setStyle(Paint.Style.FILL);
        p.setColor(skillColor);
        p.setStrokeWidth(1);
        canvas.drawCircle(center, center, innerCircle-20, p);

        //绘制圆环
        this.paint.setColor(skillColor);
        //this.paint.setARGB(255, 212 ,225, 233);
        this.paint.setStrokeWidth(ringWidth);
        //创建绘制圆环的范围
        RectF oval = new RectF();
        oval.top = this.ringWidth / 2 + 2;
        oval.left = this.ringWidth / 2 + 2;
        oval.right = width - this.ringWidth / 2 - 2;
        oval.bottom = width - this.ringWidth / 2 - 2;
        //扫过的角度,也就是能力值,注意一定要用float计算,不然会算出0
        float sweepAngle = (skillPoint / 100f) * 360f;
        //绘制能力值
        canvas.drawArc(oval, 270, sweepAngle, false, this.paint);

        p.setTextSize(TEXT_SIZE);
        p.setColor(skillTextColor);
        p.setTextAlign(Paint.Align.CENTER);
        canvas.drawText(skillText, 0, skillText.length(), center, center, p);
    }

这个控件大概就是这样了,但是还有一些东西需要处理,比如点击、颜色根据能力改变等等,我们在下一篇文章中会继续讨论。

结尾+扯淡

下一篇文章会继承这篇文章创建的自定义控件,实现更多更强大的功能。
继续扯淡,其实我很想做Android,但是目前成熟一些的做Android的公司投了简历就像石沉大海,完全没有回应了,目前收到的offer也有几个,但是都是做J2EE的,是我最熟练的,却不是最感兴趣的。找工作好辛苦啊,坚持了这么久,也不能就这么放弃,继续加油吧~
脑袋里还有很多的想法,比如我即将要做的课程设计(协作平台)、或者是社交日历等,如果我以后动手实现了,我也一定会分享出来。
本项目已经托管到了Github
分类: 前端

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注