自定义BannerView,显示下个一个view部分界面
来源:互联网 发布:cf手游刷枪刷钻石软件 编辑:程序博客网 时间:2024/05/29 09:19
先上效果图:
一.view的分析
首先看到view的轮播效果,一般人会想到用viewpager来实现这个功能,但是viewpager之间的view是独立了,看这个view是个独立的整体,所以viewpager不大适合这个是用场景,另外看到横向滑动的效果可能会想到horizontalscrollview,但注意到的是每一次滑动是移动一屏,但是horizontalscrollview是不断的移动,综合上述情况,我采用了水平方向的LinerLayout来实现上述效果。
二.功能的实现
下一个view会有少许部分界面在上一个view的页面中,这时候需要控制第一个view的宽度,第一view的宽度通过获取屏幕的宽度减去下个view显示在第一个view中的宽度
int margin; int width; margin = DensityUtils.dp2px(PriceRankActivity.this,50); width = ScreenUtils.getScreenWidth(PriceRankActivity.this);
ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams((width - margin), ViewGroup.LayoutParams.WRAP_CONTENT); ll_addview.addView(view,lp);
给LinerLayout加上手势监听,判断一个view是向左划还是向右划,在处理相应的滑动逻辑
ll_addview.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { int margin = DensityUtils.dp2px(PriceRankActivity.this,50); int width = ScreenUtils.getScreenWidth(PriceRankActivity.this); switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: mPosX = (int) motionEvent.getX(); mPosY = (int) motionEvent.getY(); Log.e("Main"," mPosX " + mPosX + " mPosY " + mPosY); break; case MotionEvent.ACTION_MOVE: mCurPosX = (int) motionEvent.getX(); mCurPosY = (int) motionEvent.getY(); Log.e("Main"," mCurPosX " + mCurPosX + " mCurPosY " + mCurPosY); break; case MotionEvent.ACTION_UP:// if (mCurPosY - mPosY > 0// && (Math.abs(mCurPosY - mPosY) > 25)) {// //向下滑動//// } else if (mCurPosY - mPosY < 0// && (Math.abs(mCurPosY - mPosY) > 25)) {// //向上滑动//// } if (mCurPosX - mPosX < 0 && (Math.abs(mCurPosX - mPosX) > 25)){ //Toast.makeText(PriceRankActivity.this,"向左滑动",Toast.LENGTH_SHORT).show(); if (isAnimalPaly){ switch (mCurrentPosiotn){ case PERVIOUS: initAnimation(); mCurrentPosiotn = MIDDLEN; break; case MIDDLEN: first = (width - margin); second = 2*(width - margin); initAnimation(); mCurrentPosiotn = NEXT; break; case NEXT: first = 2*(width - margin); second = 2*(width - margin); initAnimation(); //ll_addview.scrollTo(2*(width-margin),0); break; } } } if (mCurPosX - mPosX > 0 && (Math.abs(mCurPosX - mPosX) > 25)){ // Toast.makeText(PriceRankActivity.this,"向右滑动",Toast.LENGTH_SHORT).show(); if (isAnimalPaly){ switch (mCurrentPosiotn){ case PERVIOUS:// first = 0;// second = (width - margin); break; case MIDDLEN: first = (width - margin); second = 0; initAnimation(); mCurrentPosiotn = PERVIOUS; first = 0; second = (width - margin); break; case NEXT: first = 2*(width - margin); second = (width - margin); initAnimation(); mCurrentPosiotn = MIDDLEN; break; } } } break; } return true; } });
控制view的移动,这里通过LinerLayout的scrollTo方法,每一屏的切换就是当前view的宽度,如果直接调用scrollTo方法切换,是瞬时切换,没有动画效果,想要让view的切换有动画效果,这时候要引入ValueAnimator方法,通过监听这个差值器的方法,通过把这个切换的距离切成一小段,通过不断的调用scrollTo方法让view缓慢的移动到指定的位置
private void initAnimation(){ ValueAnimator valueAnimator;valueAnimator = ValueAnimator.ofFloat(first,second); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float mAnimatorValue = (float) valueAnimator.getAnimatedValue(); ll_addview.scrollTo((int)mAnimatorValue,0); } }); valueAnimator.setDuration(500); valueAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { isAnimalPaly = false; } @Override public void onAnimationEnd(Animator animator) { Log.e(" animator ","动画结束"); isAnimalPaly = true; } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); valueAnimator.start(); }
三.贴上完整代码
package smartworld.com.wcjsview;import android.animation.Animator;import android.animation.ValueAnimator;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.TextView;import java.util.ArrayList;import java.util.List;/** * Created by ${charles} on 2017/11/22. * * @desc ${TODO} */public class PriceRankActivity extends AppCompatActivity{ private LinearLayout ll_addview; int mPosX,mPosY,mCurPosX,mCurPosY; public static final int PERVIOUS = 1; public static final int MIDDLEN = 2; public static final int NEXT = 3; private int mCurrentPosiotn = PERVIOUS; int margin; int width; private int first,second; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_rank); ll_addview = (LinearLayout) findViewById(R.id.ll_addview); margin = DensityUtils.dp2px(PriceRankActivity.this,50); width = ScreenUtils.getScreenWidth(PriceRankActivity.this); first = 0; second = (width - margin); ll_addview.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { int margin = DensityUtils.dp2px(PriceRankActivity.this,50); int width = ScreenUtils.getScreenWidth(PriceRankActivity.this); switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: mPosX = (int) motionEvent.getX(); mPosY = (int) motionEvent.getY(); Log.e("Main"," mPosX " + mPosX + " mPosY " + mPosY); break; case MotionEvent.ACTION_MOVE: mCurPosX = (int) motionEvent.getX(); mCurPosY = (int) motionEvent.getY(); Log.e("Main"," mCurPosX " + mCurPosX + " mCurPosY " + mCurPosY); break; case MotionEvent.ACTION_UP:// if (mCurPosY - mPosY > 0// && (Math.abs(mCurPosY - mPosY) > 25)) {// //向下滑動//// } else if (mCurPosY - mPosY < 0// && (Math.abs(mCurPosY - mPosY) > 25)) {// //向上滑动//// } if (mCurPosX - mPosX < 0 && (Math.abs(mCurPosX - mPosX) > 25)){ //Toast.makeText(PriceRankActivity.this,"向左滑动",Toast.LENGTH_SHORT).show(); if (isAnimalPaly){ switch (mCurrentPosiotn){ case PERVIOUS: initAnimation(); mCurrentPosiotn = MIDDLEN; break; case MIDDLEN: first = (width - margin); second = 2*(width - margin); initAnimation(); mCurrentPosiotn = NEXT; break; case NEXT: first = 2*(width - margin); second = 2*(width - margin); initAnimation(); //ll_addview.scrollTo(2*(width-margin),0); break; } } } if (mCurPosX - mPosX > 0 && (Math.abs(mCurPosX - mPosX) > 25)){ // Toast.makeText(PriceRankActivity.this,"向右滑动",Toast.LENGTH_SHORT).show(); if (isAnimalPaly){ switch (mCurrentPosiotn){ case PERVIOUS:// first = 0;// second = (width - margin); break; case MIDDLEN: first = (width - margin); second = 0; initAnimation(); mCurrentPosiotn = PERVIOUS; first = 0; second = (width - margin); break; case NEXT: first = 2*(width - margin); second = (width - margin); initAnimation(); mCurrentPosiotn = MIDDLEN; break; } } } break; } return true; } }); initData(); addItemView(); } private boolean isAnimalPaly = true; private void initAnimation(){ ValueAnimator valueAnimator;valueAnimator = ValueAnimator.ofFloat(first,second); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float mAnimatorValue = (float) valueAnimator.getAnimatedValue(); ll_addview.scrollTo((int)mAnimatorValue,0); } }); valueAnimator.setDuration(500); valueAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { isAnimalPaly = false; } @Override public void onAnimationEnd(Animator animator) { Log.e(" animator ","动画结束"); isAnimalPaly = true; } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); valueAnimator.start(); } String[] str = {"本田","丰田","三菱"}; String[] str2 = {"1","2","3"}; private void addItemView(){ int width = ScreenUtils.getScreenWidth(this); for (int z = 0; z < listList.size(); z++ ){ View view = View.inflate(this,R.layout.item_price_rank,null); LinearLayout ll_root = (LinearLayout) view.findViewById(R.id.ll_root); List<PriceBean> priceBeanList = listList.get(z); for (int i=0; i < priceBeanList.size(); i++){ View childView = View.inflate(this,R.layout.item_child,null); TextView tv_title = (TextView) childView.findViewById(R.id.tv_title); TextView tv_num = (TextView) childView.findViewById(R.id.tv_num); tv_title.setText(priceBeanList.get(i).getTitle()); tv_num.setText(priceBeanList.get(i).getNum()); ll_root.addView(childView); } if (z == 2){ ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams((width), ViewGroup.LayoutParams.WRAP_CONTENT); ll_addview.addView(view,lp); }else { int margin = DensityUtils.dp2px(this,50); ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams((width - margin), ViewGroup.LayoutParams.WRAP_CONTENT); ll_addview.addView(view,lp); } } } private List<List<PriceBean>> listList = new ArrayList<>(); private void initData(){ List<PriceBean> list1 = new ArrayList<>(); list1.add(new PriceBean("1","本田")); list1.add(new PriceBean("2","本田")); list1.add(new PriceBean("3","本田")); List<PriceBean> list2 = new ArrayList<>(); list2.add(new PriceBean("1","宝马")); list2.add(new PriceBean("2","宝马")); list2.add(new PriceBean("3","宝马")); List<PriceBean> list3 = new ArrayList<>(); list3.add(new PriceBean("1","奔驰")); list3.add(new PriceBean("2","奔驰")); list3.add(new PriceBean("3","奔驰")); listList.add(list1); listList.add(list2); listList.add(list3); } class PriceBean{ String num; String title; public PriceBean(String num, String title) { this.num = num; this.title = title; } public String getNum() { return num; } public void setNum(String num) { this.num = num; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }}
项目地址
阅读全文
2 0
- 自定义BannerView,显示下个一个view部分界面
- 将一个Activity分割成两部分,每个部分显示一个自定义View
- Android自定义View(七)--很low的bannerView
- 一个简单的自定义View,可以显示上图下字
- 自定义View同时显示3个Fragment
- 一个view显示多个model(一个页面显示多张表)
- AndroidStudio 2.0下怎么处理自定义View不显示而且预览界面看不到的问题以及报错问题
- 一个可以在界面顶部展现的自定义 View
- 自定义View界面大合集
- 一个界面内 动画切换多个view(webview)
- Android 自定义View(一) 介绍和一个简单TextView显示
- 一个用粒子动画显示文字的 Android 自定义 View
- 自定义View的显示
- .net mvc4 一个 view 显示多个 model
- android_fragment一个屏幕显示多个view.xml
- .net mvc4 一个 view 显示多个 model
- android自定义view,不显示view情况下,把view转为bitmap
- 歌词显示控件的实现下——自定义View
- 【caffe】配置python接口----pycaffe
- 使用google的gson自定义日期转换
- ffmpeg MP3转wav
- 区块链 2 创建多重合约钱包
- MapReduce的yarn框架整理
- 自定义BannerView,显示下个一个view部分界面
- childNodes中nodeType的12种类型
- AsyncTask
- 139. Word Break
- 数据结构实验之图论九:最小生成树
- Markdown
- Android_AlertDialog与PopWindow
- React Native按钮的实现
- Spring Security OAuth2实现使用JWT