200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 自定义控件实现(淘宝头条/京东快报)垂直循环滚动栏目

自定义控件实现(淘宝头条/京东快报)垂直循环滚动栏目

时间:2020-03-13 04:30:04

相关推荐

自定义控件实现(淘宝头条/京东快报)垂直循环滚动栏目

1、通过继承LinearLayout的方式

①自定义属性

<?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>

②自定义View

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);}/*** 初始化属性*/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(PLEX_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;}//关闭清空TypedArray 防止内存泄露array.recycle();}/*** 测量控件的宽高*/@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(PLEX_UNIT_SP, TEXTSIZE, getResources().getDisplayMetrics()));mPaint.setStyle(Paint.Style.STROKE);canvas.drawText("瑞士维氏军刀", TEXTSIZE, getHeight() * 2 / 3, mPaint);//写文字2/3的高度}/*** 设置数据*/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;}}/*** 垂直滚蛋*/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();}/*** 屏幕 旋转*/@Overrideprotected void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);}}

③数据适配器

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");}}/*** 获取数据的条数*/public int getCount() {return mDatas == null ? 0 : mDatas.size();}/*** 获取摸个数据*/public AdverNotice getItem(int position) {return mDatas.get(position);}/*** 获取条目布局*/public View getView(JDAdverView parent) {return LayoutInflater.from(parent.getContext()).inflate(R.layout.item, null);}/*** 条目数据适配*/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();}});}}

④条目的布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/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>

⑤代码中使用:

initData();final JDViewAdapter adapter = new JDViewAdapter(datas);final JDAdverView tbView = (JDAdverView) findViewById(R.id.jdadver);tbView.setAdapter(adapter);//开启线程滚东tbView.start();

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"));}

2、ViewFlipper实现

<ViewFlipperandroid:id="@+id/flipper"android:layout_width="match_parent"android:layout_height="wrap_content"android:autoStart="true"android:flipInterval="900" //设置滚动的时间android:inAnimation="@anim/push_up_in"//切入动画android:outAnimation="@anim/push_up_out" >//切出动画<include layout="@layout/news_one" /><include layout="@layout/news_two" /><include layout="@layout/news_three" /><include layout="@layout/news_four"/></ViewFlipper>

3、TextSwitcher实现

<?xml version="1.0" encoding="utf-8"?><RelativeLayoutxmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffff"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="60dp"android:layout_centerInParent="true"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:background="@drawable/bg"android:gravity="center_vertical"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:paddingLeft="5dp"android:text="京东"android:textSize="16sp"android:textStyle="bold" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#ff0000"android:padding="5dp"android:paddingLeft="5dp"android:text="快报"android:textColor="#ffffff"android:textSize="16sp"android:textStyle="bold" /><Viewandroid:layout_width="1dp"android:layout_height="50dp"android:layout_marginLeft="5dp"android:layout_marginRight="5dp"android:background="#e0e0e0" /><!-- flipInterval可能是一次切换的时间 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:gravity="center_vertical"android:layout_gravity="center_vertical"android:orientation="horizontal"><TextSwitcherandroid:id="@+id/textSwitcher_tag"android:layout_width="match_parent"android:layout_height="50dp"android:layout_weight="3"android:padding="0dp"android:gravity="center_vertical"android:layout_gravity="center_vertical"android:inAnimation="@anim/push_up_in"android:outAnimation="@anim/push_up_out"></TextSwitcher><TextSwitcherandroid:id="@+id/textSwitcher_title"android:layout_width="match_parent"android:layout_height="50dp"android:layout_weight="1"android:padding="0dp"android:gravity="center_vertical"android:layout_gravity="center_vertical"android:inAnimation="@anim/push_up_in"android:outAnimation="@anim/push_up_out"></TextSwitcher></LinearLayout></LinearLayout></RelativeLayout>

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textSwitcher_tag= (TextSwitcher) findViewById(R.id.textSwitcher_tag);textSwitcher_title= (TextSwitcher) findViewById(R.id.textSwitcher_title);textSwitcher_title.setFactory(new ViewSwitcher.ViewFactory() {@Overridepublic View makeView() {final TextView tv = newTextView(MainActivity.this);tv.setTextSize(PLEX_UNIT_SP, 14);tv.setPadding(20, 20, 20, 20);return tv;}});textSwitcher_tag.setFactory(new ViewSwitcher.ViewFactory() {@Overridepublic View makeView() {final TextView tv = newTextView(MainActivity.this);tv.setTextSize(PLEX_UNIT_SP, 18);tv.setPadding(30, 20, 20,20);tv.setTextColor(Color.RED);tv.setBackgroundResource(R.drawable.corner);return tv;}});final Handler handler = new Handler();handler.postDelayed(new Runnable() {@Overridepublic void run() {textSwitcher_tag.setText(tags[curStr++ %tags.length]);textSwitcher_title.setText(titles[curStr++ % titles.length]);handler.postDelayed(this, 1000);}}, 1000);}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。