Android組合控制元件(無限輪播圖)
android 自定義控制元件
是的,真的是自定義控制元件。
相對於自定義控制元件的控制元件是什麼呢?當然是原生的控制元件啦!
比如說:
1、Button 、TextView 、ImageView 、EditText等(view)。
2、LinearLayout RelativeLayout FrameLayout等(viewGroup)。
好理解嗎?後面會解釋的哦!
View和ViewGroup的關係
繼承關係:
首先所有的控制元件繼承於View,包括ViewGroup也是!所以:
哎呀,畫了賊久,嘻嘻!話不多說,看圖就OK了!當然,上面這個圖是不夠完整的,意思意思一下就好了,嘻嘻!是吧!
還畫少了一條線,哈哈!太粗心咯!這上面這個是繼承關係!
組合(巢狀)關係:
除了上面的繼承關係,我們都知道,一個LinearLayout裡面可以巢狀LinearLayout或者其他的控制元件,從這種關係裡頭,我們可以發現,這種巢狀是一種遞迴的關係,直到什麼時候呢,哈哈!直到控制元件是一個非ViewGroup為止,也就是當前控制元件不能容納控制元件為止。那什麼控制元件不能容納控制元件呢?比如說:Button ImageView TextView等等。也就是非ViewGroup的子類控制元件,嘻嘻!
再畫一個圖片吧:
看明白了嗎?就這麼一個輪迴,嘻嘻。不是六世,是根據需求而定,嗯。好的!
對於Activity來說,是怎麼樣的結構呢?其實它是一個窗體Window---->PhoneWindow----->DecorView(這個是ViewGroup)所以它可以包含子控制元件。
自定義View和自定義控制元件
在這裡呢,我要跟大家解釋一件事。我在小時候學習android的時候,真的沒能分清自定義控制元件和自定義view的區別。現在呢,大概可以解釋了:
自定義控制元件:也就是控制元件的組合使用,定義為一個新的控制元件
自定義view:也就是這個view之前是沒有的。比如說,QQ聊天條目的橫劃刪除,QQ的側滑縮放這些都是。相對來說,什麼是非自定義view呢?由前面的view結構,我們可以知道,ImageView,Button,TextView...這些都是android已經定義好的view。
ViewPager的組合例子:
ViewPager在絕大多數的App開發中,都使用到的。無論是圖片的輪播,還是在一個Activity裡的多個Fragment的切換。當然,這也是一個經典的例子。
這裡呢,我就使用我們部落格的幾張滾動圖片,在實際開發中,圖片多數是從伺服器中獲取的,絕少數是寫死的。
思路:
1、佈局不說了吧,我後面直接上佈局;
2、首先先實現viewpager的資料,設定介面卡;
3、動態地新增點;
4、對viewpager進行監聽,動態地切換紅色的點。
---------------------------------------------------------------------------------------------------------------
佈局如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="160dp"
tools:context=".MainActivity" >
<!-- 圖片 -->
<android.support.v4.view.ViewPager
android:id="@+id/vp_pic"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- 字型描述部分 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#66000000"
android:gravity="center"
android:orientation="vertical"
android:padding="3dp" >
<TextView
android:id="@+id/tv_des"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="圖片描述"
android:textColor="#ffffff" />
<!-- 圓點容器 -->
<LinearLayout
android:id="@+id/ll_point_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<!-- 動態的新增點 -->
</LinearLayout>
</LinearLayout>
</RelativeLayout>
JAVA程式碼:(有一個小Bug,我沒fix)
public class MainActivity extends Activity {
private ViewPager mViewPager;
private TextView mDes;
private LinearLayout mPointContainer;
private int[] mDatas = { R.drawable.pic1, R.drawable.pic2, R.drawable.pic3,
R.drawable.pic4 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//
initView();
initDatas();
initEvent();
//
}
/**
* 初始化UI
*/
private void initView() {
setContentView(R.layout.activity_main);
//
mPointContainer = (LinearLayout) this
.findViewById(R.id.ll_point_container);
mDes = (TextView) this.findViewById(R.id.tv_des);
mViewPager = (ViewPager) this.findViewById(R.id.vp_pic);
//
}
/**
* 初始化資料
*/
private void initDatas() {
// 設定介面卡
mViewPager.setAdapter(new MyAdapter());
// 根據圖片的張數來新增點的個數
for (int i = 0; i < mDatas.length; i++) {
// 如果不是第一個的話就新增一個leftMargin
ImageView iv = new ImageView(this);
iv.setBackgroundResource(R.drawable.point_white);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
Dp2dx.dp2dx(this, 10), Dp2dx.dp2dx(this, 10));
if (i != 0) {
params.leftMargin = Dp2dx.dp2dx(this, 10);
}
iv.setLayoutParams(params);
mPointContainer.addView(iv);
}
selectedPoint(0);
}
/**
* 介面卡
*
* @author Administrator
*
*/
private class MyAdapter extends PagerAdapter {
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// 銷燬
container.removeView((View) object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView iv = new ImageView(MainActivity.this);
iv.setBackgroundResource(mDatas[position % mDatas.length]);
container.addView(iv);
return iv;
}
@Override
public int getCount() {
if (mDatas != null && mDatas.length != 0) {
return Integer.MAX_VALUE;// 返回最大值,用於無限迴圈
}
return 0;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
}
private void initEvent() {
// 預設選中第一個,也就是第0個
mViewPager.setCurrentItem(Integer.MAX_VALUE / 2);
// 對viewPager的監聽
viewPagerEvent();
}
private void viewPagerEvent() {
// 對viewPager進行監聽
mViewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
// 頁面滑動時的監聽,選中當前的顏色
selectedPoint(arg0 % mDatas.length);
// 修改描述資訊,這裡直接做演示的話就直接修改文字,在實際開發中,可以另外一個方法來控制描述
mDes.setText("圖片描述" + arg0 % mDatas.length);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
// 這個方法用於選中遠點的顏色
public void selectedPoint(int position) {
// 遍歷一次,除Position之外,設定成白色
for (int i = 0; i < mDatas.length; i++) {
ImageView point = (ImageView) mPointContainer.getChildAt(i);
if (i != position) {
// 設定成白色
point.setBackgroundResource(R.drawable.point_white);
} else {
// 設定成紅色
point.setBackgroundResource(R.drawable.point_read);
}
}
}
}
另外還有一個小工具類:把dp轉成px
package com.sunofbeaches.viewpagerdemo;
import android.content.Context;
public class Dp2dx {
public static int dp2dx(Context context, int dp) {
float density = context.getResources().getDisplayMetrics().density;
int dx = (int) (dp * density + 0.5f);
return dx;
}
}
完成的效果大概就這樣子咯:gif,有點大,可能載入需要一點時間:
如果需要自動輪播的話,可以使用handler,或者使用線成池都可以解決的。這很簡單,去嘗試一下吧!