Android 仿淘宝商品详情页

其实差很多,只是简单的模仿里面的一个效果而已。稍微做个笔记。

效果是这个样子的。

上面那几个 ITEM 可以点击,还有下面模块滑动的时候,对应的 ITEM 要变色,就俩需求。

这里我采用的都是最直接的方式,上面那个用 LinearLayout 包几个按钮,下面那个用 ScrallView,整体用 FrameLayout 包起来。(这种简单的叠加别用耗性能的 RelativeLayout)

上布局代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zhanglf.goodsdetail.MainActivity">

<com.zhanglf.goodsdetail.ScrollViewDIY
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zhanglf.goodsdetail.MainActivity">


<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">


<View
android:id="@+id/view_one"
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_marginTop="45dp"
android:background="@android:color/holo_orange_dark"
android:orientation="vertical">

</View>

<View
android:id="@+id/view_two"
android:layout_width="match_parent"
android:layout_height="700dp"
android:background="@android:color/holo_blue_bright"
android:orientation="vertical">

</View>

<View
android:id="@+id/view_three"
android:layout_width="match_parent"
android:layout_height="600dp"
android:background="@android:color/holo_green_dark"
android:orientation="vertical">

</View>

<View
android:id="@+id/view_four"
android:layout_width="match_parent"
android:layout_height="800dp"
android:background="@android:color/holo_red_light"
android:orientation="vertical">
</View>

</LinearLayout>

</com.zhanglf.goodsdetail.ScrollViewDIY>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_purple"
android:orientation="horizontal">

<Button
android:id="@+id/bt_item1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text=" Item 1 "/>

<Button
android:id="@+id/bt_item2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text=" Item 2 "/>

<Button
android:id="@+id/bt_item3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text=" Item 3 "/>

<Button
android:id="@+id/bt_item4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text=" Item 4 "/>
</LinearLayout>
</FrameLayout>

写 4 个 ITEM 按钮的点击事件,下面模块的跳转用 ScrollViewsmoothScrollTo() 方法就好了。

这个方法需要传入两个参数,分别是 x 和 y 的坐标。这里 x 我们传 0 就好了。y 的话直接用 getTop(); 获取距离顶部的距离。

这里有一点要注意Activity 生命周期中,onStart, onResume, onCreate 都不是真正 visible 的时间点,真正的visible 时间点是 onWindowFocusChanged() 函数被执行时。

所以 getTop() 要放在 onWindowFocusChanged() 里面执行,否则过早调用 getTop(),比如在 onCreate() 中调用,可能会因为这个 view 还没有被加到 rootview 中获取到的值都是 0。

第二个需求是要根据滑动距离让上面对应的 ITEM 变色。

这个时候需要实现 ScrollViewOnScollChangedListener 接口,但是会发现 Call requires API 23 。

所以,最好还是自己创建一个类继承系统的 ScrollView 来兼容低版本。(不是很清楚为什么 Google要将 onScrollChanged() 定义成 protected)

上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class ScrollViewDIY extends ScrollView {
public ScrollViewDIY(Context context) {
this(context, null);
}

public ScrollViewDIY(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public ScrollViewDIY(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

}

@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (onScollChangedListener != null) {
onScollChangedListener.onScrollChanged(this, x, y, oldx, oldy);
}
}

//接口回调

public void setOnScollChangedListener(OnScollChangedListener onScollChangedListener) {
this.onScollChangedListener = onScollChangedListener;
}


public interface OnScollChangedListener {

void onScrollChanged(ScrollViewDIY scrollView, int x, int y, int oldx, int oldy);

}

private OnScollChangedListener onScollChangedListener;
}

有个小技巧,关于自定义的 View ,每次都要写那三段构造函数是不是很烦?

其实 Google 早就想到了,直接打 ViewConstructors 就可以自动完成了。你也可以在这里修改该 Templates :

然后就没有然后了,直接判断范围了好了。

整体代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
public class MainActivity extends AppCompatActivity {

private ScrollViewDIY mScroll;
private Button mBt1;
private Button mBt2;
private Button mBt3;
private Button mBt4;
private View mView1;
private View mView2;
private View mView3;
private View mView4;
private int mTop1;
private int mTop2;
private int mTop3;
private int mTop4;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intView();
}

private void intView() {
mScroll = (ScrollViewDIY) findViewById(R.id.scrollView);
mView1 = findViewById(R.id.view_one);
mView2 = findViewById(R.id.view_two);
mView3 = findViewById(R.id.view_three);
mView4 = findViewById(R.id.view_four);
mBt1 = (Button) findViewById(R.id.bt_item1);
mBt2 = (Button) findViewById(R.id.bt_item2);
mBt3 = (Button) findViewById(R.id.bt_item3);
mBt4 = (Button) findViewById(R.id.bt_item4);

mBt1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mScroll.smoothScrollTo(0,mTop1);
}
});
mBt2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mScroll.smoothScrollTo(0,mTop2);
}
});
mBt3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mScroll.smoothScrollTo(0,mTop3);
}
});
mBt4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mScroll.smoothScrollTo(0,mTop4);
}
});
mScroll.setOnScollChangedListener(new ScrollViewDIY.OnScollChangedListener() {
@Override
public void onScrollChanged(ScrollViewDIY scrollView, int x, int y, int oldx, int oldy) {
if (y<mTop2) {
setColor(1);
} else if (y>=mTop2&&y<mTop3) {
setColor(2);
} else if (y>=mTop3&&y<mTop4) {
setColor(3);
} else if (y>=mTop4) {
setColor(4);
}
}
});
}

private void setColor(int index) {
mBt1.setTextColor(Color.BLACK);
mBt2.setTextColor(Color.BLACK);
mBt3.setTextColor(Color.BLACK);
mBt4.setTextColor(Color.BLACK);
switch (index) {
case 1:
mBt1.setTextColor(Color.RED);
break;
case 2:
mBt2.setTextColor(Color.RED);
break;
case 3:
mBt3.setTextColor(Color.RED);
break;
case 4:
mBt4.setTextColor(Color.RED);
break;
}

}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
mTop1 = mView1.getTop();
mTop2 = mView2.getTop();
mTop3 = mView3.getTop();
mTop4 = mView4.getTop();
}

}

就是这么简单。