前言
仍然是一个小demo,这个添加了如果中间项没有到中间位置时,自动滚动至中间位置,并且在滑动过程中,不改变中间项
先上效果图
源码如下:
public class MiddleHorizal extends HorizontalScrollView {
private onMiddleItemChangedListener middleItemChangedListener;
private Handler mHandler = new Handler();
private int currentX = 0;//记录当前滚动的距离
private int scrollDealy = 50;//滚动监听间隔
int current = -1; //当前位于中间item的位置
double halfScreenWidth; //屏幕的一半宽度
LinearLayout content; //内容view
public MiddleHorizal(Context context, AttributeSet attrs) {
super(context, attrs);
halfScreenWidth = 1.0 * getScreenWidth(context) / 2;
}
public MiddleHorizal(Context context) {
super(context, null);
}
/**
* 滚动监听runnable
*/
private Runnable scrollRunnable = new Runnable() {
@Override
public void run() {
if (getScrollX() == currentX) {
//滚动停止 取消监听线程
mHandler.removeCallbacks(this);
setMiddleItem();
return;
}
else {
//手指离开屏幕 view还在滚动的时候
mHandler.postDelayed(this, scrollDealy);
}
currentX = getScrollX();
}
};
/**
* 判断中间项 并滚动至屏幕中央
*/
private void setMiddleItem() {
if (content != null) {
int minWidth = -1;
int lastCurrent = current;
int minDivider = 0;
//判断距离屏幕中间距离最短的item
for (int i = 0; i < content.getChildCount(); i++) {
int divider = (int) ((content.getChildAt(i).getX() + 1.0 * content.getChildAt(i).getWidth() / 2 - currentX) - halfScreenWidth);
int absDivider = Math.abs(divider);
if (minWidth < 0) {
minWidth = absDivider;
}
else if (minWidth > absDivider) {
minWidth = absDivider;
minDivider = divider;
current = i;
}
}
//如果中间项变化,则恢复原状
if (lastCurrent != current && lastCurrent >= 0) {
TextView lastMiddleView = (TextView) content.getChildAt(lastCurrent);
lastMiddleView.setTextSize(20);
lastMiddleView.setTextColor(Color.RED);
}
//滚动至中间位置
scrollBy(minDivider, 0);
middleItemChangedListener.middleItemChanged(current);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
//手指在上面移动的时候 取消滚动监听线程
mHandler.removeCallbacks(scrollRunnable);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
//手指移动的时候
mHandler.post(scrollRunnable);
break;
}
return super.onTouchEvent(ev);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//初始化,使得中间项在屏幕中间位置
if (getChildCount() > 0 && current < 0 && middleItemChangedListener != null) {
content = (LinearLayout) getChildAt(0);
setMiddleItem();
}
}
public void setMiddleItemChangedListener(onMiddleItemChangedListener middleItemChangedListener) {
this.middleItemChangedListener = middleItemChangedListener;
}
/**
* 获取屏幕宽度
*/
public static int getScreenWidth(Context context) {
Display display = ((WindowManager) context
.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
return display.getWidth();
}
/**
* 回调,将中间项位置传递出去
*/
interface onMiddleItemChangedListener {
void middleItemChanged(int current);
}
}
<!--中间位置做个小标记-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="1"
/>
<com.qianqian.demo.viewdemo.MiddleHorizal
android:id="@+id/horizontalScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:layout_centerVertical="true"
android:orientation="horizontal"
/>
</com.qianqian.demo.viewdemo.MiddleHorizal>
<TextView
android:id="@+id/currentItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/horizontalScrollView"
android:layout_centerHorizontal="true"
/>
public class MainActivity extends Activity implements MiddleHorizal.onMiddleItemChangedListener {
LinearLayout contentLinear;
MiddleHorizal horizontalScrollView;
private ArrayList<String> items = new ArrayList<>();
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contentLinear = (LinearLayout) findViewById(R.id.content);
textView = (TextView) findViewById(R.id.currentItem);
horizontalScrollView = (MiddleHorizal) findViewById(R.id.horizontalScrollView);
horizontalScrollView.setMiddleItemChangedListener(this);
contentLinear.removeAllViews();
for (int i = 0; i < 50; i++) {
TextView child = new TextView(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(80, ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER;
child.setTextSize(20);
child.setTextColor(Color.RED);
child.setGravity(Gravity.CENTER);
child.setText("" + i);
items.add(""+i);
contentLinear.addView(child, params);
}
}
@Override
public void middleItemChanged(int current) {
TextView currentTxt = (TextView) contentLinear.getChildAt(current);
currentTxt.setTextSize(24);
currentTxt.setTextColor(Color.GREEN);
String s = items.get(current);
textView.setText("位于中间位置的是" + s);
}
}
补充
添加点击某一项,将该item移动到中间位置的事件,这样子做:
//在自定义view中添加方法
/**
* 点击item,将该item移动至中间位置
*
* @param v 点击的item
*/
public void setMiddleItem(View v) {
if (v.getTag() != null && (int) v.getTag() != current) {
TextView lastMiddleView = (TextView) content.getChildAt(current);
lastMiddleView.setTextSize(20);
lastMiddleView.setTextColor(Color.RED);
int divider = (int) ((v.getX() + 1.0 * v.getWidth() / 2 - getScrollX()) - halfScreenWidth);
scrollBy(divider, 0);
current = (int) v.getTag();
middleItemChangedListener.middleItemChanged(current);
}
}
\\activity中添加子view的时候,设置tag并在click方法中调用即可
child.setTag(i);//将postion设为tag,设置位置
child.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
horizontalScrollView.setMiddleItem(v);
}
});
网友评论