实现思路其实很简单,就是一个自定义的LinearLayout,并且textView能够循环垂直滚动,而且条目可以点击,显示区域最多显示2个条目,并且还有交替的属性垂直移动的动画效果,通过线程来控制滚动的实现。
不多说看效果:
代码实现
我们先来为控件设置自定义属性:
<?xml version="1.0" encoding="utf-8"?><resources><declare-styleable name="JDAdverView"><attr name="gap" format="integer" /><attr name="animDuration" format="integer"/></declare-styleable></resources>
//获取自定义属性TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.JDAdverView);mAdverHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, jdAdverHeight, getResources().getDisplayMetrics());int gap = array.getInteger(R.styleable.JDAdverView_gap, mGap);int animDuration = array.getInteger(R.styleable.JDAdverView_animDuration, mAnimDuration);//关闭清空TypedArray,防止内存泄露array.recycle();
然后呢,我们来看一下条目的布局:
<?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="60dp"android:background="#ffffff"android:gravity="center_vertical"android:orientation="horizontal"><TextViewandroid:id="@+id/tag"android:textColor="#ff0000"android:layout_marginLeft="10dp"android:text="最新"android:background="@drawable/corner"android:textSize="18sp"android:padding="5dp"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/title"android:layout_marginLeft="10dp"android:singleLine="true"android:ellipsize="end"android:textSize="20sp"android:text="价格惊呆!电信千兆光纤上市"android:textColor="#000000"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout>
布局很简单,效果呢:
不解释,我们来写适配器了:
package com.example.jdadvernotice;import android.view.LayoutInflater;import android.view.View;import android.widget.TextView;import android.widget.Toast;import com.example.jdadvernotice.entity.AdverNotice;import com.example.jdadvernotice.view.JDAdverView;import java.util.List;/*** Created by Administrator on 2016/3/20.* 京东广告栏数据适配器**/public class JDViewAdapter {private List<AdverNotice> mDatas;public JDViewAdapter(List<AdverNotice> mDatas) {this.mDatas = mDatas;if (mDatas == null || mDatas.isEmpty()) {throw new RuntimeException("nothing to show");}}/*** 获取数据的条数* @return*/public int getCount() {return mDatas == null ? 0 : mDatas.size();}/*** 获取摸个数据* @param position* @return*/public AdverNotice getItem(int position) {return mDatas.get(position);}/*** 获取条目布局* @param parent* @return*/public View getView(JDAdverView parent) {return LayoutInflater.from(parent.getContext()).inflate(R.layout.item, null);}/*** 条目数据适配* @param view* @param data*/public void setItem(final View view, final AdverNotice data) {TextView tv = (TextView) view.findViewById(R.id.title);tv.setText(data.title);TextView tag = (TextView) view.findViewById(R.id.tag);tag.setText(data.url);//你可以增加点击事件view.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//比如打开urlToast.makeText(view.getContext(), data.url, Toast.LENGTH_SHORT).show();}});}}
然后我们就来自定义view:
package com.example.jdadvernotice.view;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.content.Context;import android.content.res.Configuration;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;import android.widget.LinearLayout;import com.example.jdadvernotice.JDViewAdapter;import com.example.jdadvernotice.R;/*** Created by zengyu on 2016/3/20.*/public class JDAdverView extends LinearLayout {//控件高度private float mAdverHeight = 0f;//间隔时间private final int mGap = 4000;//动画间隔时间private final int mAnimDuration = 1000;//显示文字的尺寸private final float TEXTSIZE = 20f;private JDViewAdapter mAdapter;private final float jdAdverHeight = 50;//显示的viewprivate View mFirstView;private View mSecondView;//播放的下标private int mPosition;//线程的标识private boolean isStarted;//画笔private Paint mPaint;public JDAdverView(Context context) {this(context, null);}public JDAdverView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public JDAdverView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs, defStyleAttr);}/*** 初始化属性* @param context* @param attrs* @param defStyleAttr*/private void init(Context context, AttributeSet attrs, int defStyleAttr) {//设置为垂直方向setOrientation(VERTICAL);//抗锯齿效果mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//获取自定义属性TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.JDAdverView);mAdverHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, jdAdverHeight, getResources().getDisplayMetrics());int gap = array.getInteger(R.styleable.JDAdverView_gap, mGap);int animDuration = array.getInteger(R.styleable.JDAdverView_animDuration, mAnimDuration);if (mGap <= mAnimDuration) {gap = mGap;animDuration = mAnimDuration;}//关闭清空TypedArrayarray.recycle();}/*** 设置数据*/public void setAdapter(JDViewAdapter adapter) {this.mAdapter = adapter;setupAdapter();}/*** 开启线程*/public void start() {if (!isStarted && mAdapter.getCount() > 1) {isStarted = true;postDelayed(mRunnable, mGap);//间隔mgap刷新一次UI}}/*** 暂停滚动*/public void stop() {//移除handle更新removeCallbacks(mRunnable);//暂停线程isStarted = false;}/*** 设置数据适配*/private void setupAdapter() {//移除所有viewremoveAllViews();//只有一条数据,不滚东if (mAdapter.getCount() == 1) {mFirstView = mAdapter.getView(this);mAdapter.setItem(mFirstView, mAdapter.getItem(0));addView(mFirstView);} else {//多个数据mFirstView = mAdapter.getView(this);mSecondView = mAdapter.getView(this);mAdapter.setItem(mFirstView, mAdapter.getItem(0));mAdapter.setItem(mSecondView, mAdapter.getItem(1));//把2个添加到此控件里addView(mFirstView);addView(mSecondView);mPosition = 1;isStarted = false;}}/*** 测量控件的宽高** @param widthMeasureSpec* @param heightMeasureSpec*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (LayoutParams.WRAP_CONTENT == getLayoutParams().height) {getLayoutParams().height = (int) mAdverHeight;} else {mAdverHeight = getHeight();}if (mFirstView != null) {mFirstView.getLayoutParams().height = (int) mAdverHeight;}if (mSecondView != null) {mSecondView.getLayoutParams().height = (int) mAdverHeight;}}/*** 画布局** @param canvas*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mPaint.setColor(Color.WHITE);mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, TEXTSIZE, getResources().getDisplayMetrics()));mPaint.setStyle(Paint.Style.STROKE);canvas.drawText("瑞士维氏军刀", TEXTSIZE, getHeight() * 2 / 3, mPaint);//写文字2/3的高度}/*** 垂直滚蛋*/private void performSwitch() {//属性动画控制控件滚动,y轴方向移动ObjectAnimator animator1 = ObjectAnimator.ofFloat(mFirstView, "translationY", mFirstView.getTranslationY() - mAdverHeight);ObjectAnimator animator2 = ObjectAnimator.ofFloat(mSecondView, "translationY", mSecondView.getTranslationY() - mAdverHeight);//动画集AnimatorSet set = new AnimatorSet();set.playTogether(animator1, animator2);//2个动画一起set.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {//动画结束mFirstView.setTranslationY(0);mSecondView.setTranslationY(0);View removedView = getChildAt(0);//获得第一个子布局mPosition++;//设置显示的布局mAdapter.setItem(removedView, mAdapter.getItem(mPosition % mAdapter.getCount()));//移除前一个viewremoveView(removedView);//添加下一个viewaddView(removedView, 1);}});set.setDuration(mAnimDuration);//持续时间set.start();//开启动画}private AnimRunnable mRunnable = new AnimRunnable();private class AnimRunnable implements Runnable {@Overridepublic void run() {performSwitch();postDelayed(this, mGap);}}/*** 销毁View的时候调用*/@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();//停止滚动stop();}/*** 屏幕 旋转** @param newConfig*/@Overrideprotected void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);}}
从上面可以看出,控件最多可以显示2个条目,并且用线程控制,根据条目的下标轮流滚动显示。
具体使用代码:
初始化数据:
private void initData() {datas.add(new AdverNotice("瑞士维氏军刀 新品满200-50","最新"));datas.add(new AdverNotice("家居家装焕新季,讲199减100!","最火爆"));datas.add(new AdverNotice("带上相机去春游,尼康低至477","HOT"));datas.add(new AdverNotice("价格惊呆!电信千兆光纤上市","new"));}
绑定适配器开启滚动线程:
initData();final JDViewAdapter adapter = new JDViewAdapter(datas);final JDAdverView tbView = (JDAdverView) findViewById(R.id.jdadver);tbView.setAdapter(adapter);//开启线程滚东tbView.start();
就写到这里吧,很晚了睡觉,欢迎大家前来拍砖。
以上内容是针对Android高仿京东垂直循环滚动新闻栏的全部介绍,希望对大家以上帮助!
新闻热点
疑难解答