公告轮播条控件ViewFlipper精炼详解

一、前期基础知识储备

ViewFlipper是安卓原生控件,平时开发中用到的次数不多,一次偶然看见的时候,发现对这个控件的印象一片空白,今天本节文章就是给自己补课,UI控件还是没有完全熟悉ε=(´ο`*)))唉!

首先,看看官方文档中的描述:

从官方文档中,我们可以看见ViewFlipper继承自ViewAnimator和FrameLayout,里面封装好了动画的实现逻辑,每次ViewFlipper中只能展现一次元素,我们可以设置ViewFlipper中的元素动态更换。

这里,笔者将使用两种ViewFlipper的实现方式,一种比较直观,另一种比较优雅,读者可以根据自己情况参考。

二、上代码,具体实现

(1)主布局文件中放入一个ViewFlipper

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.administrator.viewflipper.MainActivity">

    <ViewFlipper
        android:id="@+id/vf"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:autoStart="true"
        android:background="#fff"
        android:flipInterval="3000"
        android:inAnimation="@anim/anim_marquee_in"
        android:outAnimation="@anim/anim_marquee_out"
        android:paddingLeft="30dp" />
</RelativeLayout>

这里就参数做一个说明:

autoStart——设置是否自动播放

flipInterval——设置轮播动画时间

inAnimation——设置淡入动画,这里简单设置为平移动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="1500"
        android:fromYDelta="100%p"
        android:toYDelta="0"/>
</set>

outAnimation——设置淡出动画,这里简单设置为平移动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="1500"
        android:fromYDelta="0"
        android:toYDelta="-100%p"/>
</set>

查看ViewFlipper的官方文档,可以发现对ViewFlippr进行设置的属性有蛮多,感兴趣的读者可以参考官方文档

(2)ViewFlipper的item布局文件

布局也比较简单,这里采用了线性布局,计划在一个ViewFlipper中实现两个item的布局。同样的布局文件,复制两份,更换里面的文字即可。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="8dp"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/shape"
            android:text="热点"
            android:textColor="#F14C00"
            android:textSize="12sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:padding="3dp"
            android:singleLine="true"
            android:text="你是最适合19.9元T恤的人!"
            android:textColor="#333"
            android:textSize="14sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/shape"
            android:text="热点"
            android:textColor="#F14C00"
            android:textSize="12sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:padding="3dp"
            android:singleLine="true"
            android:text="《高能少年团加长版》一期上线!"
            android:textColor="#333"
            android:textSize="14sp" />
    </LinearLayout>
</LinearLayout>

这是shape的布局文件,简单为“热点”做个形状,美观一些。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="@android:color/white" />
    <stroke
        android:width="1dp"
        android:color="@android:color/holo_red_light" />

    <corners android:radius="3dp" />

</shape>

(3)主Activity代码

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewFlipper vf = (ViewFlipper) findViewById(R.id.vf);

        vf.addView(View.inflate(this, R.layout.view_advertisement_01, null));
        vf.addView(View.inflate(this, R.layout.view_advertisement_02, null));
        vf.addView(View.inflate(this, R.layout.view_advertisement_03, null));
    }
}

通过inflate方法,把定义好的三个item布局文件放入到ViewFlipper中,这里放入的额动作采用了ViewFlipper的addView()方法,第一个参数为view,第二个参数一般为null即可。

运行效果如图:

 

通过以上的三个步骤,我们简单实现了一个公告轮播的效果,但是实际上是不够优雅的,我们要展现的三组文字,分别放到了三组布局文件中,分别定义,这样有XML布局文件中大量的代码重复,例子中是只有三组,但是如果要求的轮播公告更多一点的话,XML布局文件就更加的臃肿了,如果要求更改的话……实现方式十分的不雅。

这里给出一个更为优雅的实现方式,只在XML中设置一个item的布局文件,里面的textView的text不在XML中设置,而是在Activity代码中动态的设置,这样,无论多少组item需要实现,都只要在Activity代码中进行字符串的设置即可,布局文件不需要动,就算再次修改,也十分的方便。

优雅·优雅

(1)主布局文件中放置ViewFlpper——同上

(2)仅为ViewFlipper设置一个布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:weightSum="2">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:padding="3dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/shape"
            android:paddingBottom="3dp"
            android:paddingLeft="5dp"
            android:paddingRight="5dp"
            android:paddingTop="3dp"
            android:text="热点"
            android:textColor="@android:color/holo_red_light" />

        <TextView
            android:id="@+id/tv_title1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:ellipsize="end"
            android:gravity="center_vertical"
            android:maxLines="1"
            android:paddingLeft="5dp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/ll_second"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:padding="3dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/shape"
            android:paddingBottom="3dp"
            android:paddingLeft="5dp"
            android:paddingRight="5dp"
            android:paddingTop="3dp"
            android:text="热点"
            android:textColor="@android:color/holo_red_light" />

        <TextView
            android:id="@+id/tv_title2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:ellipsize="end"
            android:gravity="center_vertical"
            android:maxLines="1"
            android:paddingLeft="5dp" />
    </LinearLayout>
</LinearLayout>

可以看到,里面的内容和第一次的实现方式很相似,就是第二个textView中没有设置text,这里我们把text的设置任务放在了Activity中进行,实现一个动态的布局思路。

(3)主Activity文件

public class MainActivity extends AppCompatActivity {
    private Context context;
    private ViewFlipper viewFlipper;
    private List<String> titles;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        context = this;
        viewFlipper = (ViewFlipper) findViewById(R.id.vf);
        initData();
        setViews();

    }

    private void setViews() {
        if (titles.size() > 0) {
            //计算ViewFlipper视图的数目
            int viewNum = titles.size() / 2 + 1;
            for (int i = 0; i < viewNum; i++) {
                //每一个视图的第一个新闻标题中集合中的下标值
                final int position = i * 2;
                View itemView = View.inflate(context, R.layout.item_view, null);
                TextView tvTitle1 = (TextView) itemView.findViewById(R.id.tv_title1);
                TextView tvTitle2 = (TextView) itemView.findViewById(R.id.tv_title2);
                LinearLayout ll = (LinearLayout) itemView.findViewById(R.id.ll_second);
				//得到textView实例之后,用集合中的数据进行填充,通过循环完成
                tvTitle1.setText(titles.get(position));

                //判断第二行是否有数据,这里考虑进奇数视图的情况
                if (position + 1 < titles.size()) {
                    tvTitle2.setText(titles.get(position + 1));
                } else {
                    //表示该视图的第二个标题没有数据,隐藏第二行布局
                    ll.setVisibility(View.GONE);
                }

                //标题1的点击事件
                tvTitle1.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(context, titles.get(position), Toast.LENGTH_SHORT).show();
                    }
                });

                //标题2的点击事件
                tvTitle2.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(context, titles.get(position + 1), Toast.LENGTH_SHORT).show();
                    }
                });

                viewFlipper.addView(itemView);
            }
        }
    }
    private void initData() {
        titles = new ArrayList();
        titles.add("你是最适合19.9元T恤的人!");
        titles.add("《高能少年团加长版》一期上线!");
        titles.add("古人是如何买年货的!");
        titles.add("为何让手机24小时不离身!");
        titles.add("我用了20年才看懂还珠格格");
        titles.add("你的英伦腔是装的还是真的?");
        titles.add("梁实秋:人没有不懒的");
    }
}

可以看到我们把所有要加入到ViewFlipper中的数据通过initData()的方法进行初始化,把所有的数据都放入到一个集合里面,然后通过循环,把集合对应位置的数据逐个放入ViewFlipper中,这样就实现了和第一种方法中一样的效果,但是代码量大大缩减,减少了很多重复的XML布局代码,而且后期修改维护也十分的方便。

运行效果图如下:和第一种方法的效果类似,但是处理了奇数的item情况。




猜你喜欢

转载自blog.csdn.net/weixin_41101173/article/details/80159954