您的位置:首页 > 移动开发 > Android开发

如何用按钮控制循环HorizontalScrollView水平滑动

2016-08-14 10:42 330 查看
如何用按钮控制循环HorizontalScrollView水平滑动

最近做了一个用按钮控制循环滚轴水平滑动的控件,在这里总结一下。

要控制滑动那么先要实现一个能够循环滚动的滚轴,以下是我的思路:

首先实现这个需求我想到的方案有两个:

第一:做一个适配器,这个适配器的主要方法是通过获取存入图片的list的长度,接着通过除余的方法循环的返回相应位置的View再添加上去。

缺点:当图片的多的时候,并且没有通过LruCache,获取采样率,压缩等方法进行处理的时候,很可能出现加载缓慢或者出现OOM情况。

第二:在初始化界面的时候,只从适配器读取少量的view加载在父容器之上。把显示的view存入一个showList的队列中,把剩下的view存入一个waitList的队列中。

滚动的时候分为两种情况,一个是向前滚动,一个向后滚动。

向前滚动:

只要getScrollx()超过了子视图的宽度位置处,执行以下动作:



每一次的滑动将showList的头放到waitList的尾,waitList的头放到showList的尾。

向后滚动:

只要getScrollx()检测到是从父容器0处开始滑动,执行以下动作:



每一次的滑动将showList的尾放到waitList的头,waitList的尾放到showList的头。

这样就能避免像网上那样通过记录位置,来计算子视图的位置了。

思路就能想到这么多,可能还有更棒的思路,本人才疏学浅只能想到这么多。

循环队列的思想完成之后,就开始做按钮控制滑动的工作。

那么按钮控制自定义控件HorizontalScrollView的滑动,就会想到两种设计模式,一种是通过装饰模式扩展其中的功能,另一种是通过桥接模式用自定义的按钮和原来的功能组合,控制HorizontalScrollView的功能,封装好之后暴露一个接口就能完成

这里展示桥接模式相对简单的应用方法,下面是截取部分代码:

文件MyHorizntalScrollView.java

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.IllegalFormatCodePointException;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

import javax.security.auth.PrivateCredentialPermission;

import com.example.adapter.HorizontalAdapter;
import com.example.newgoldinglauncher.R;

import android.R.integer;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;

public class MyHorizontalScroller extends HorizontalScrollView implements OnTouchListener,setChildViewListener{
private static LinearLayout container;
private static Map<View, Integer> map = new HashMap<View, Integer>();//每个view的编号
private static Map<View, Integer> containermap = new HashMap<View, Integer>();//每个view在父容器的编号
private int ScreenWidth;
private int currentIndex;
private int FirstIndex = 0;
private static HorizontalAdapter adapter;
private OnItemCilckListener mListener;
private CurrentImageChangeListener cListener;
private static LinkedList<Integer> showList = new LinkedList<Integer>();//子view显示列表
private static LinkedList<Integer> waitlist = new LinkedList<Integer>();//子view待显示列表
private int LastInterceptX;
private int LastInterceptY;
private int ChildWidth;
private int ChildHeight;
private static int childCountonScreen;//当前屏幕子view个数
private LinearLayout parentLayout;
private VelocityTracker vTracker;
private static int firstposition;

public interface OnItemCilckListener{
public void onClick(View v,int pos);
}

public interface CurrentImageChangeListener{
public void OnCurrentChange(int position,View v);
}

public MyHorizontalScroller(Context context){
super(context);
init(context);
}

public MyHorizontalScroller(Context context,AttributeSet attrs){
super(context, attrs);
init(context);

}

public MyHorizontalScroller(Context context,AttributeSet attrs,int defStyle){
super(context, attrs, defStyle);
init(context);
}

private void init(Context context){
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
ScreenWidth = outMetrics.widthPixels;
vTracker = VelocityTracker.obtain();
}

@Override
protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
container = (LinearLayout)getChildAt(0);
}

protected void loadNextImg(){//手动滑动,向后滑动
//Log.e("movenext", "here");
if(adapter.getCount() == 0){
return;
}
int waittoadd = waitlist.removeFirst();
int deleteshow = showList.removeFirst();
showList.addLast(waittoadd);
waitlist.addLast(deleteshow);
int index = showList.get(childCountonScreen - 1);
map.remove(container.getChildAt(0));
containermap.remove(container.getChildAt(0));
container.removeViewAt(0);
View view = adapter.getView(index, null, container);
container.addView(view);
map.put(view, index);
Log.e("index", ""+index);
//      for(Integer value : map.values()){
//          Log.e("mapvalue", ""+value);
//      }
for(int k = 0;k < childCountonScreen;k++){
containermap.put(container.getChildAt(k), k);
}
String clazz = this.getClass().getName();
//Log.e("nextthis", ""+clazz);
view.setOnTouchListener(this);
//setchildviewListener();
if(cListener != null){
notifyCurrentImgChange();
}
}

protected void loadPreImg(){//手动滑动,向前滑动
if(adapter.getCount() == 0){
return;
}
int last = container.getChildCount() - 1;
map.remove(container.getChildAt(last));
containermap.remove(container.getChildAt(last));
container.removeViewAt(last);
int waittoadd = waitlist.removeLast();
int deleteshow = showList.removeLast();
showList.addFirst(waittoadd);
waitlist.addFirst(deleteshow);
int index = showList.get(0);
View view = adapter.getView(index, null, container);
container.addView(view,0);
map.put(view, index);
for(int k = 0;k < childCountonScreen;k++){
containermap.put(container.getChildAt(k), k);
}
String clazz = this.getClass().getName();
Log.e("prethis", ""+clazz+last);
view.setOnTouchListener(this);
for(Integer value : map.values()){
Log.e("mapvalue",""+value);
}
//setchildviewListener();
if(cListener != null){
notifyCurrentImgChange();
}
}

//  @Override
//  public boolean onInterceptTouchEvent(MotionEvent event){
//      boolean Intercept = false;
//      int x = (int)event.getX();
//      int y = (int)event.getY();
//
//      switch (event.getAction()) {
//      case MotionEvent.ACTION_DOWN:
//          Intercept = false;
//          break;
//
//      case MotionEvent.ACTION_MOVE:
//          int x1 = (int)event.getX();
//          int y1 = (int)event.getY();
//          int deltaX = x - x1;
//          int deltaY = y - y1;
//          if(Math.abs(deltaX) < 10 && Math.abs(deltaY) < 10){
//              Intercept = false;
//          }else {
//              Intercept = true;
//          }
//          break;
//      case MotionEvent.ACTION_UP:
//          Intercept = true;
//      default:
//          break;
//      }
//      return Intercept;
//  }

@Override
public boolean onTouch(View v, MotionEvent ev) {
// TODO Auto-generated method stub
int scrollX = getScrollX();
vTracker.computeCurrentVelocity(1000);
float xVelocity =  vTracker.getXVelocity();
//Log.e("xv", ""+xVelocity);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.e("down", "here");
int id = 0;
if(mListener != null){
Log.e("mListener", "notnull"+container.getChildCount());
for(int i = 0;i < container.getChildCount();i++){
container.getChildAt(i).setBackgroundColor(Color.WHITE);//将所有子view背景涂白
}

mListener.onClick(v,containermap.get(v));
Log.e("hclick",""+id);
}
Log.e("mListener", "null");
break;

case MotionEvent.ACTION_MOVE:
Log.e("scrollx", ""+scrollX);
if(scrollX >= ChildWidth){
Log.e("go", "h");
loadNextImg();
}else if(scrollX == 0){
Log.e("back", "h");
loadPreImg();
}
break;

case MotionEvent.ACTION_UP:
vTracker.clear();
break;
default:
break;
}
return true;
}

public void initData(HorizontalAdapter adapter){
this.adapter = adapter;
container = (LinearLayout) getChildAt(0);
final View view = adapter.getView(0, null, container);
container.addView(view);
if(ChildWidth == 0 && ChildHeight == 0){
int w =View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(w, h);
ChildWidth = view.getMeasuredWidth();
ChildHeight = view.getMeasuredHeight();
Log.e("childwidth",""+ChildWidth);
//childCountonScreen = (ScreenWidth/ ChildWidth == 0)?(ScreenWidth / ChildWidth) + 1:(ScreenWidth / ChildWidth) + 1;
childCountonScreen = 9;
}
initScreen(childCountonScreen);
}

public void initScreen(int childCountonScreen){
container = (LinearLayout) getChildAt(0);
container.removeAllViews();
map.clear();
showList.clear();
waitlist.clear();
Log.e("countonScreen","" + childCountonScreen);
for(int i = 0;i < childCountonScreen;i++){
View view = adapter.getView(i, null, container);
view.setOnTouchListener(this);
container.addView(view);
map.put(view, i);
containermap.put(view, i);
currentIndex = i;
showList.add(i);
}
Log.e("count", ""+(adapter.getCount()-childCountonScreen));
for(int i = childCountonScreen;i < adapter.getCount();i++){
waitlist.add(i);
}
}

public void notifyCurrentImgChange(){
int first = showList.peek();
for (int i = 0; i < container.getChildCount(); i++)
{
container.getChildAt(i).setBackgroundColor(Color.WHITE);
}

cListener.OnCurrentChange(first,container.getChildAt(0));
}

public void setOnClickItemListener(OnItemCilckListener mListener){
this.mListener = mListener;
}

public void setOnCurrentImageChangeListener(CurrentImageChangeListener cListener){
this.cListener = cListener;
}

public void PressToScroll(){
scrollBy(ChildWidth, 0);
}

@Override
protected void onDetachedFromWindow(){
vTracker.recycle();
super.onDetachedFromWindow();
}

public int getChildId(int i){
return map.get(container.getChildAt(i));
}

public int getChildWidth(){
return ChildWidth;
}

public View getChildView(int i){

return container.getChildAt(i);
}

public int getAllCount(){
return adapter.getCount();
}

public int getCount(){
return container.getChildCount();
}

public int getNextNumber(View v){
Log.e("containermap",""+containermap.get(v));
return containermap.get(v);
}

public View getInitView(){
return container.getChildAt(0);
}

public void setfirstposition(View v){
int position = containermap.get(v);

this.firstposition = position;
}

public int getfirstposition(){
Log.e("fposition", ""+firstposition);
return firstposition;
}

@Override
public void setchildviewListener() {
// TODO Auto-generated method stub
for(int i = 0;i < childCountonScreen;i++){
container.getChildAt(i).setOnTouchListener(this);
}
}

}


文件(控制滑动的按钮)MyImageView.java:

import java.util.HashMap;
import java.util.LinkedList;

import com.example.newgoldinglauncher.R;
import com.example.widget.MyHorizontalScroller.OnItemCilckListener;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.view.View.OnTouchListener;;

public class MyImageView extends ImageView implements OnTouchListener{
private MyHorizontalScroller horizontalScroller;
private OnImageClickListener iListener;
private HashMap<View, Integer> selector = new HashMap<View, Integer>();
private LinkedList<Integer> blueList = new LinkedList<Integer>();
private LinkedList<Integer> whiteList = new LinkedList<Integer>();
private int change;
private View selectView;//选中的view
private static int k;
private int fixpos = 0;
private int startpos;

public interface OnImageClickListener  {
public void click(View v);
}

public MyImageView(Context context){
super(context);
horizontalScroller = new MyHorizontalScroller(context);
this.setOnTouchListener(this);
init();
}

public MyImageView(Context context,AttributeSet attrs){
super(context, attrs);
horizontalScroller = new MyHorizontalScroller(context, attrs);
this.setOnTouchListener(this);
init();
}

public MyImageView(Context context,AttributeSet attrs,int defStyle){
super(context, attrs, defStyle);
horizontalScroller = new MyHorizontalScroller(context, attrs, defStyle);
this.setOnTouchListener(this);
init();
}

public void setOnImageClickListener(OnImageClickListener iListener){
this.iListener = iListener;
}

public void init(){
horizontalScroller.setOnClickItemListener(new OnItemCilckListener() {

@Override
public void onClick(View v, int pos) {
// TODO Auto-generated method stub
v.setBackgroundColor(Color.parseColor("#AA024DA4"));
horizontalScroller.setfirstposition(v);
}
});
}

public void NextImage(View v){//按按钮后滚轴向后移动
int distance = horizontalScroller.getChildWidth();
horizontalScroller.scrollBy(distance, 0);
horizontalScroller.loadNextImg();
k = horizontalScroller.getfirstposition();
Log.e("k", ""+k);
View view = horizontalScroller.getChildView(k);
for(int i = 0;i < horizontalScroller.getCount();i++){
horizontalScroller.getChildView(i).setBackgroundColor(Color.WHITE);
}
view.setBackgroundColor(Color.parseColor("#AA024DA4"));
//selectView = view;

}

public void PreImage(View v){//按按钮滚轴向前移动
int distance = horizontalScroller.getChildWidth();
horizontalScroller.scrollBy(-distance, 0);
int scrollx = getScrollX();
View view;
if(scrollx == 0){
horizontalScroller.loadPreImg();
view = horizontalScroller.getChildView(0);
view.setBackgroundColor(Color.parseColor("#AA024DA4"));
}else {
int i = horizontalScroller.getNextNumber(v) - 1;
if(i < 0){
i = horizontalScroller.getCount() - 1;
}
view = horizontalScroller.getChildView(i);
view.setBackgroundColor(Color.parseColor("#AA024DA4"));
}

}

public void ClickImage(View v){

if(this.getId() == R.id.previous){
PreImage(v);
}else if(this.getId() == R.id.next){
NextImage(v);
}
}

public void getImgId(View v){
this.selectView = v;
}

@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int x1 = 0;
int x2 = 0;
int y1 = 0;
int y2 = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = (int)event.getX();
y1 = (int)event.getY();
if(iListener != null){
iListener.click(v);
}
this.setBackgroundColor(Color.parseColor("#AA024DA4"));
for(int i = 0;i < horizontalScroller.getCount();i++){
horizontalScroller.getChildView(i).setBackgroundColor(Color.WHITE);
}
selectView.setBackgroundColor(Color.parseColor("#AA024DA4"));
break;
case MotionEvent.ACTION_UP:
x2 = (int)event.getX();
y2 = (int)event.getY();
this.setBackgroundColor(Color.parseColor("#FFFFFF"));
ClickImage(selectView);
break;
default:
break;
}
return true;

}
}


MyImageView暴露了一个setOnImageClickListner的接口,只要实现其中接口,就能将耦合降低。

下面是MainActivity.java文件:

public class MainActivity extends Activity {
private LedView ledview;
private TextView cityname;
private TextView tempView;
private MyImageView previous;
private MyImageView next;
private HorizontalListView fountionList;
private MyHorizontalScroller horizontalScroller;
private HorizontalAdapter adapter;
private int[] imgId = new int[]{R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,
R.drawable.h,R.drawable.i,R.drawable.j,R.drawable.k};
private HashMap<Integer, View>selector = new HashMap<Integer, View>();
private static int position;
private ArrayList<Integer> imgList = new ArrayList<Integer>();
private View selectView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ledview = (LedView) findViewById(R.id.led_view);
cityname = (TextView)findViewById(R.id.cityname);
tempView = (TextView)findViewById(R.id.temp);
horizontalScroller = (MyHorizontalScroller)findViewById(R.id.fountion_list);
previous = (MyImageView)findViewById(R.id.previous);
next = (MyImageView)findViewById(R.id.next);
init(this);

}

private void init(Context context){//初始化界面
LayoutInflater inflater = getLayoutInflater();
for(int i = 0;i < imgId.length;i++){
imgList.add(imgId[i]);
Log.e("imgId",String.valueOf(imgId[i]));
}
adapter = new HorizontalAdapter(context, imgList);
horizontalScroller.setOnClickItemListener(new OnItemCilckListener() {//自己编写的接口,为了将选中的view的背景变蓝
@Override
public void onClick(View v, int pos) {
// TODO Auto-generated method stub
Log.e("item", "pos"+pos);
v.setBackgroundColor(Color.parseColor("#AA024DA4"));
horizontalScroller.setfirstposition(v);
selectView = v;
position = pos;
Log.e("position", ""+position);
}
});
horizontalScroller.initData(adapter);
//      horizontalScroller.setOnCurrentImageChangeListener(new CurrentImageChangeListener() {
//
//          @Override
//          public void OnCurrentChange(int position, View v) {
//              // TODO Auto-generated method stub
//              v.setBackgroundColor(Color.parseColor("#AA024DA4"));
//          }
//      });

previous.setOnImageClickListener(new OnImageClickListener() {//向前滑动控件的接口

@Override
public void click(View v) {
// TODO Auto-generated method stub
Log.e("previous", "here");
if(selectView == null){
selectView = horizontalScroller.getInitView();
}else {
previous.getImgId(selectView);
}

}
});

next.setOnImageClickListener(new OnImageClickListener() {//向后滑动控件

@Override
public void click(View v) {
// TODO Auto-generated method stub
Log.e("next", "here");
if(selectView == null){
selectView = horizontalScroller.getInitView();
}else {
next.getImgId(selectView);
}

}
});

}

@Override
protected void onResume(){
super.onResume();
ledview.start();
}

@Override
protected void onStop(){
super.onStop();
ledview.stop();
}
}


这里面我犯了一个小错误:在控制滑动的时候声明了一个新的MyHorizontalScrollView。当时忘记了导致自己没有添加相应的监听器。最好在初始化的时候,传入原来的Horizontal,这样就能减少内存的申请,优化这个控件。

感谢鸿洋大神那一段代码对我的启发。

http://blog.csdn.net/lmj623565791/article/details/38140505

这是代码全貌地址:

https://github.com/yjy239/ComplexUI
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 控件 图片