您的位置:首页 > 其它

自定义view:图片显示指示器

2015-03-06 11:00 239 查看
      本篇文章使用Gallally控件和自定义view,实现一个带有图片指示器的图片集的展示效果。

      1.实现的效果

      显示一组可以滑动的图片,随着图片的切换,指示器小圆点也随着切换。

      2.自定义view的步骤

          (1)、自定义View的属性

          (2)、在View的构造方法中获得我们自定义的属性

          (3)、重写onMesure

          (4)、重写onDraw

          (3)不一定是必须的,当然了大部分情况下还是需要重写的。

           1、自定义View的属性,首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。

           

<?xml version="1.0" encoding="utf-8"?>
<resources>

<declare-styleable name="FlowIndicator">
<attr name="count" format="integer" />
<attr name="space" format="dimension" />
<attr name="point_size" format="dimension" />
<attr name="point_seleted_color" format="color|reference" />
<attr name="point_normal_color" format="color|reference" />
<attr name="point_radius" format="dimension" />
</declare-styleable>

</resources>


我们定义了5个属性,format是值该属性的取值类型:

一共有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag;

            在图片展示的布局中,我们声明Gallery控件以及自定义属性。布局文件head_view.xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.dream.myqiyi"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<Gallery
android:id="@+id/home_gallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:spacing="5dip" />

<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#65000000"
android:orientation="vertical" >

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="5dip"
android:layout_marginTop="5dip"
android:text="承影之奇艺UIdemo"
android:textColor="#ffffff"
android:textSize="18dip" />

<com.dream.myqiyi.widget.FlowIndicator
android:id="@+id/myView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dip"
app:count="4"
android:gravity="center"
app:point_normal_color="#45000000"
app:point_radius="3dip"
app:point_seleted_color="#ffffff"
app:point_size="5dip"
app:space="10dip" />
</LinearLayout>

</FrameLayout>


记住,一定要引入 xmlns:app="http://schemas.android.com/apk/res/com.dream.myqiyi" 命名空间,后面的包路径指的是项目的package。

             2, 自定义FlowIndicator类继承View类,在自定义的FlowIndicator类构造方法中,获得我们的自定义样式属性,并重写View类的onMeasure()和onView()方法。

public class FlowIndicator extends View {
private int count;
private float space, radius;
private int point_normal_color, point_seleted_color;

// 选中
private int seleted = 0;

// background seleted normal

public FlowIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.FlowIndicator);

count = a.getInteger(R.styleable.FlowIndicator_count, 4);
space = a.getDimension(R.styleable.FlowIndicator_space, 9);
radius = a.getDimension(R.styleable.FlowIndicator_point_radius, 9);

point_normal_color = a.getColor(
R.styleable.FlowIndicator_point_normal_color, 0x000000);
point_seleted_color = a.getColor(
R.styleable.FlowIndicator_point_seleted_color, 0xffff07);

int sum = attrs.getAttributeCount();
if (Constans.DEBUG) {
String str = "";
for (int i = 0; i < sum; i++) {
String name = attrs.getAttributeName(i);
String value = attrs.getAttributeValue(i);
str += "attr_name :" + name + ": " + value + "\n";
}
Log.i("attribute", str);
}
a.recycle();
}

public void setSeletion(int index) {
this.seleted = index;
invalidate();
}

public void setCount(int count) {
this.count = count;
invalidate();
}

public void next() {
if (seleted < count - 1)
seleted++;
else
seleted = 0;
invalidate();
}

public void previous() {
if (seleted > 0)
seleted--;
else
seleted = count - 1;
invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setAntiAlias(true);

float width = (getWidth() - ((radius * 2 * count) + (space * (count - 1)))) / 2.f;

for (int i = 0; i < count; i++) {
if (i == seleted)
paint.setColor(point_seleted_color);
else
paint.setColor(point_normal_color);
canvas.drawCircle(width + getPaddingLeft() + radius + i
* (space + radius + radius), getHeight() / 2, radius, paint);

}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}

private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);

if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = (int) (getPaddingLeft() + getPaddingRight()
+ (count * 2 * radius) + (count - 1) * radius + 1);
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}

private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);

if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = (int) (2 * radius + getPaddingTop() + getPaddingBottom() + 1);
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}

}


          在onMeasure函数中,系统帮我们测量的高度和宽度都是MATCH_PARNET,当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT,或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法”:重写之前先了解MeasureSpec的specMode,一共三种类型:

EXACTLY:一般是设置了明确的值或者是MATCH_PARENT

AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT

UNSPECIFIED:表示子布局想要多大就多大,很少使用。

需要重写onMeasure方法,计算自定义view的大小。

         3,Gallery数据适配器类

public class GalleryAdapter extends BaseAdapter {
Context mContext;
int[] res = new int[] { R.drawable.t1, R.drawable.t2,
R.drawable.t3, R.drawable.t1, R.drawable.t2,
R.drawable.t3, R.drawable.t1, R.drawable.t2,
R.drawable.t3 };

public GalleryAdapter(Context cnt) {

4000
this.mContext = cnt;
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return res.length;
}

@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}

@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
// TODO Auto-generated method stub
if (arg1 == null) {
arg1 = LayoutInflater.from(mContext).inflate(R.layout.gallery_item,
null);
}
ImageView img = (ImageView) arg1.findViewById(R.id.home_img);
img.setImageResource(res[arg0]);
return arg1;
}
}

            4,主Activity

public class HomeActivity extends Activity {
static final int SCROLL_ACTION = 0;
int[] tags = new int[] { 0, 0, 0, 0, 0 };
Gallery mGallery;
GalleryAdapter mGalleryAdapter;
FlowIndicator mMyView;
Timer mTimer;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.home_activity);
prepareView();
mTimer = new Timer();
mTimer.scheduleAtFixedRate(new MyTask(), 0, 4000);
}

private void prepareView() {
mExpandableListView = (ExpandableListView) findViewById(R.id.expandableListView1);
MyListAdapter adapter = new MyListAdapter();
View header = LayoutInflater.from(this).inflate(R.layout.header_view,
null);
mGallery = (Gallery) header.findViewById(R.id.home_gallery);
mMyView = (FlowIndicator) header.findViewById(R.id.myView);
mGalleryAdapter = new GalleryAdapter(this);
mMyView.setCount(mGalleryAdapter.getCount());
mGallery.setAdapter(mGalleryAdapter);
mGallery.setOnItemSelectedListener(new OnItemSelectedListener() {

@Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// TODO Auto-generated method stub
mMyView.setSeletion(arg2);
}

@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub

}
});

}

private class MyTask extends TimerTask {
@Override
public void run() {
mHandler.sendEmptyMessage(SCROLL_ACTION);
}
}

Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case SCROLL_ACTION:
int curPos = mGallery.getSelectedItemPosition();
if (curPos < mGalleryAdapter.getCount() - 1) {
curPos++;
} else {
curPos = 0;
}
/* mGallery.setLayoutAnimation(new LayoutAnimationController(
AnimationUtils.loadAnimation(HomeActivity.this,
R.anim.gallery_in)));*/
mGallery.setSelection(curPos, true);
/*MotionEvent e1 = MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN,
89.333336f, 265.33334f, 0);
MotionEvent e2 = MotionEvent.obtain(SystemClock.uptimeMillis(),
SystemClock.uptimeMillis(), MotionEvent.ACTION_UP,
300.0f, 238.00003f, 0);

mGallery.onFling(e1, e2, -1300, 0);*/
break;

default:
break;
}
}
};
}

实现图片定时自动切换和手动滑动切换。

            

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息