需求讲解:
按钮数量少于等于4个时,按钮居中显示;
按钮数量大于4个时,按钮显示如下所示:
若按钮落焦在1号、4号(相对位置)向继续向边缘移动时,若可以移动则焦点位置不动,产品推荐位移动;
若按钮落焦在2号、3号(相对位置)左右移动,和按钮落焦在1号、4号(相对位置)向继续向边缘相反方向移动时,焦点位置移动,产品推荐位不动;-
图示:
核心要点
使用以下属性使多余父元素的子控件可以显示出来
android:clipChildren="false"
android:clipToPadding="false"代码:
activity_main布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
tools:context=".MainActivity">
<HorizontalScrollView
android:id="@+id/scrollView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="259dp"
android:focusable="false"
android:scrollbars="none">
<LinearLayout
android:id="@+id/scrollLinear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
- product布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="273dp"
android:layout_height="347dp"
android:layout_marginLeft="11dp"
android:background="@drawable/selector"
android:focusable="true"
android:paddingLeft="21dp"
android:paddingRight="24dp">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="18dp" />
</RelativeLayout>
- MainActivity文件
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
private HorizontalScrollView scrollView;
private LayoutInflater inflater;
private LinearLayout linearLayout;
/**
* 按钮间距
*/
private int childLeftMargin = 11;
/**
* 按钮在scrollView中的显示四个按钮的位置
*/
private int index = 1;
/**
* 按钮数量
*/
private int count = 7;
private RelativeLayout.LayoutParams scrollLayoutParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//加载主布局
scrollView = findViewById(R.id.scrollView);
linearLayout = findViewById(R.id.scrollLinear);
//加载订购按钮布局
inflater = LayoutInflater.from(MainActivity.this);
//更改scrollView的宽高
for (int i = 0; i < count; i++) {
View view;
view = inflater.inflate(R.layout.product, linearLayout, false);
linearLayout.addView(view);
setDatas(i, view);
setListener(i, view);
}
//如果订购按扭大于5,改变scrollView的宽度
ViewTreeObserver vto = scrollView.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
public void onGlobalLayout() {
scrollView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
if (count >= 5) {
Log.i(TAG, "width=" + linearLayout.getChildAt(1).getWidth());
childLeftMargin = ((LinearLayout.LayoutParams) (linearLayout.getChildAt(1).getLayoutParams())).getMarginStart();
scrollLayoutParams = new RelativeLayout.LayoutParams(4 * linearLayout.getChildAt(0).getWidth() + 3 * childLeftMargin,
LinearLayout.LayoutParams.WRAP_CONTENT);
scrollLayoutParams.setMargins(0, scrollView.getTop(), 0, 0);
scrollLayoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
scrollView.setLayoutParams(scrollLayoutParams);
}
}
});
//默认第一个获焦
if (linearLayout.getChildAt(0) != null) {
linearLayout.getChildAt(0).requestFocus();
}
}
/**
* 设置各种事件监听
*
* @param position
* @param view
*/
public void setListener(final int position, final View view) {
Log.i(TAG, "setListener " + position);
//删除第一个订购按钮的左外边距
if (position == 0) {
ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(view.getWidth(), view.getHeight());
params.setMargins(0, view.getTop(), 0, 0);
view.setLayoutParams(params);
}
});
}
view.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (KeyEvent.ACTION_DOWN == keyEvent.getAction()) {
Log.i(TAG, "onKey " + position + " keyCode " + keyEvent.getKeyCode());
if (KeyEvent.KEYCODE_DPAD_UP == keyEvent.getKeyCode()) {
// 抖动反馈
return true;
}
if (KeyEvent.KEYCODE_DPAD_DOWN == keyEvent.getKeyCode()) {
// 抖动反馈
return true;
}
if (KeyEvent.KEYCODE_DPAD_RIGHT == keyEvent.getKeyCode()) {
// 最后一个订购按钮的右键不处理
if (position == count - 1) {
// 抖动反馈
return true;
}
if (count > 4) {
if (index == 4) {
Log.i(TAG, "rightScroll " + index);
scrollView.smoothScrollBy(view.getWidth() + childLeftMargin, 0);
}
if (index != 4) {
index++;
}
}
} else if (KeyEvent.KEYCODE_DPAD_LEFT == keyEvent.getKeyCode()) {
// 第一个订购按钮的左键不处理
if (0 == position) {
// 抖动反馈
return true;
}
if (count > 4) {
if (index == 1) {
Log.i(TAG, "leftScroll " + index);
scrollView.smoothScrollBy(-(view.getWidth() + childLeftMargin), 0);
}
if (index != 1) {
index--;
}
}
}
}
return false;
}
});
//设置订购按钮获焦事件
view.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
Log.i(TAG, "onFocus " + position);
}
}
});
}
/**
* 设置数据
*
* @param position
* @param view
*/
public void setDatas(int position, View view) {
if (count == 0) {
return;
}
TextView textView = view.findViewById(R.id.textView);
textView.setText(position + "");
}
}