Android中的自定义控件(一)
自定义控件是根据自己的需要自己来编写控件。安卓自带的控件有时候无法满足你的需求,这种时候,我们只能去自己去实现适合项目的控件。同时,安卓也允许你去继承已经存在的控件或者实现你自己的控件以便优化界面和创造更加丰富的用户体验。在平常的项目中,我们 人为的把自定义控件分为两种:一种是组合方式实现。一种是通过继承view或viewgroup及其子类实现。两者都可以实现我们想要的效果,因此,我们可以根据自己的需求,选择合适的方案。本文以案例的形式来显示几种较为常见的自定义控件。
案例一: 优酷菜单
功能介绍: 手机界面的底部中央有一个半圆,初始状态显示三级菜单,由外到内分别是第三级菜单,第二级菜单,第三级菜单。每个菜单中有一些按钮,可以用3个容器(RelativeLayout)来表示3个菜单,往里面添加按钮即可。当再次点击中心位置的图片式,隐藏外面两层的的条目。再次点击重心位置的图片时,旋转出二级菜单。点击二级菜单中心位置时,旋转出三级菜单,再次点击则隐藏三级菜单。以上就是优酷菜单要实现的功能。
实现步骤:
1. 完成布局文件。由于控件较多所以优酷菜单的布局较为复杂,但是可以在一个根布局设置三个子线性布局来包裹每一个小的控件。通过调整margin值来是使得界面更加的美观。注意3个菜单布局的顺序,先放men3,然后menu2,然后menu1,顺序不能反,因为越往后放的菜单越在界面的上方,这样面积最小的菜单1会在最上方,菜单1不会遮挡到下面的菜单2和菜单3。
2. 完成布局文件后,创建一个类,在该类中实现业务逻辑。首先要创建两个布尔类型的常量存储菜单的状态。通过swich语句判断被点击的控件是二级菜单还是一级菜单。如果是一级菜单的中心被点击,则判断三级菜单是否打开。如果三级菜单打开着,则隐藏一级菜单和二级菜单,并修改状态。如果三级菜单隐藏着则判断二级菜单是否隐藏。如果二级菜单打开着,则隐藏二级菜单。如果二级菜单隐藏则打开二级菜单。如果是二级菜单的中心被点击,则只需要判断三级菜单是否隐藏。如果三级菜单打开着,则隐藏三级菜单。如果三级菜单隐藏则打开三级菜单。同时还要修改菜单的状态。
3. 接下来可以在一个工具类中实现动画的效果。步骤2中的隐藏和显示均都是通过动画效果实现的。这里的动画效果用到的是补间动画,为RotateAnimation对象传入起始角度,结束的角度,参考对象和参考点坐标。一个小细节是将setFillAfter属性设为true,表示从结束位置开始动画,避免动画结束后又回到起始位置。隐藏和显示区别是旋转的起始角度和结束角度,这里显示设定的起始角度是-180,结束角度为0。隐藏设定的起始角度为0,结束角度为-180。当然也可以设定为其他值,取决于自己想要的效果。
4. 代码优化。快速点击按钮时会发现菜单还没隐藏完就开始显示了,或者还没显示完又隐藏了。解决方案:监听动画的开启次数来判断是否需要执行画,给动画类添加一个监听器。设置一个成员变量。当开始开始动画是执行加一操作,结束动画是执行减一操作。这样只有当常量为零时,才没有动画。因此swich语句中加入判断如果当前存在动画,等待动画执行完之后在进入下面的逻辑。
菜单选择界面的布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"> <RelativeLayout
android:id="@+id/rl_menu3"
android:layout_width="280dp"
android:layout_height="140dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level3"> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="6dp"
android:layout_marginLeft="12dp"
android:background="@drawable/channel1" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="46dp"
android:layout_marginLeft="32dp"
android:background="@drawable/channel2" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="80dp"
android:layout_marginLeft="60dp"
android:background="@drawable/channel3" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="6dp"
android:background="@drawable/channel4" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="80dp"
android:layout_marginRight="60dp"
android:background="@drawable/channel5" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="46dp"
android:layout_marginRight="32dp"
android:background="@drawable/channel6" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="6dp"
android:layout_marginRight="12dp"
android:background="@drawable/channel7" /> </RelativeLayout> <RelativeLayout
android:id="@+id/rl_menu2"
android:layout_width="180dp"
android:layout_height="90dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level2"> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="6dp"
android:layout_marginLeft="12dp"
android:background="@drawable/icon_search" /> <ImageButton
android:id="@+id/btn_menu2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="4dp"
android:background="@drawable/icon_menu" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="6dp"
android:layout_marginRight="12dp"
android:background="@drawable/icon_myyouku" /> </RelativeLayout> <RelativeLayout
android:id="@+id/rl_menu1"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/level1"> <ImageButton
android:id="@+id/btn_menu1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/icon_home" /> </RelativeLayout>
</RelativeLayout>
主界面的布局,在代码中用打气筒把菜单布局打到主界面上。
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
android:gravity="center"
tools:context="com.example.selectbar.Selectbar"> <com.example.selectbar.Rotate
android:layout_centerInParent="true"
android:id="@+id/rotate"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> </RelativeLayout>
主程序是空实现。
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity; public class Selectbar extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_selectbar);
}
}
主要逻辑的实现。
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout; import com.example.selectbar.com.example.selectbar.utils.utils; /**
* Created by huang on 2016/11/22.
*/
public class Rotate extends RelativeLayout implements View.OnClickListener {
private static final String TAG = "Rotate";
private RelativeLayout rl_menu1, rl_menu2, rl_menu3;
private boolean menu2showing = true;
private boolean menu3showing = true; public Rotate(Context context) {
super(context,null);
} public Rotate(Context context, AttributeSet attrs) {
super(context, attrs);
initdata(context);
} private void initdata(Context context) {
Log.i(TAG, "initdata: text");
View view = View.inflate(context,R.layout.activity_rolate,null);
view.findViewById(R.id.btn_menu1).setOnClickListener(this);
view.findViewById(R.id.btn_menu2).setOnClickListener(this);
rl_menu1 = (RelativeLayout) view.findViewById(R.id.rl_menu1);
rl_menu2 = (RelativeLayout) view.findViewById(R.id.rl_menu2);
rl_menu3 = (RelativeLayout) view.findViewById(R.id.rl_menu3);
addView(view);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_menu2:
if (utils.hasAnimationexcuting()) {
return;
}
if (menu3showing) {
utils.hiden(rl_menu3);
} else {
utils.show(rl_menu3);
}
menu3showing = !menu3showing;
break; case R.id.btn_menu1:
if (utils.hasAnimationexcuting()) {
return;
}
if (menu3showing) {
utils.hiden(rl_menu3);
menu3showing = false;
utils.hiden(rl_menu2, 300); } else if (menu2showing) {
utils.hiden(rl_menu2);
} else {
utils.show(rl_menu2);
}
menu2showing = !menu2showing;
break;
}
}
}
还需要一个工具类实现动画的效果。
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation; /**
* Created by huang on 2016/11/22.
*/
public class utils {
private static final String TAG = "utils";
private static void setviewclickable(View view, boolean clickable) {
view.setClickable(clickable);
if (view instanceof ViewGroup) {
ViewGroup viewgroup = (ViewGroup) view;
for (int i = 0; i < viewgroup.getChildCount(); i++) {
View child = ((ViewGroup) view).getChildAt(i);
child.setClickable(clickable);
}
}
} public static void hiden(View view) {
float fromDegreeas = 0;
float toDegrees = -180f;
rotateview(view, fromDegreeas, toDegrees, 0l);
setviewclickable(view, false);
} public static void hiden(View view, long startoffset) {
float fromDegreeas = 0;
float toDegrees = -180f;
rotateview(view, fromDegreeas, toDegrees, startoffset);
setviewclickable(view, false);
} public static void show(View view) {
float fromDegrees = -180f;
float toDegrees = 0;
rotateview(view, fromDegrees, toDegrees, 0l);
setviewclickable(view, true);
} public static boolean hasAnimationexcuting() {
return startcount > 0;
} public static void rotateview(View view, float fromDegrees, float toDegrees, long startoffset) {
int pivotXType = RotateAnimation.RELATIVE_TO_SELF;
int pivotYType = RotateAnimation.RELATIVE_TO_SELF;
float pivotXValue = 0.5f;
float pivatYValue = 1.0f;
RotateAnimation ra = new RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivatYValue);
ra.setDuration(500);
ra.setFillAfter(true);
ra.setStartOffset(startoffset);
ra.setAnimationListener(listener);
view.startAnimation(ra);
} public static int startcount;
static Animation.AnimationListener listener = new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
startcount++;
// Log.i(TAG, "onAnimationStart: " +startcount);
} @Override
public void onAnimationEnd(Animation animation) {
startcount--;
// Log.i(TAG, "onAnimationEnd: " + startcount);
} @Override
public void onAnimationRepeat(Animation animation) { }
};
}
案例二 popupwindow实现下拉列表:
功能介绍:创建一个textview,当我们点击textview时会弹出一个列表,列表中存放的是数字信息和一张删除图片。列表是用listview实现。点击删除图片可以将本条记录从列表中删除。本案例的有两种,一种是通过动画的缩放实现弹出效果,另一种是采取popupwindow。本文采用的是第二种方案。
实现步骤:
- 添加布局文件。首先要在界面上放置一个textview,在textview的右边放置一个下拉图片。为了更方便地摆放控件,可以采用相对布局,这样只要保证imageview和textview上对齐、下对齐、右对齐就可以实现要现实的效果。为了是界面更美观,可以把图片设为透明的,即背景为null。这里将popupwindow弹出来的界面用listview表示。因此还要写一个单独的listview以及每一个条目的布局,然后用打气筒打到textview的下方、
- Pupupwindow的编写。Popupwindow的编写有两个关键的步骤,一个是new一个pupupwimdow对象,将要显示的布局、布局的高和宽、是否可聚等相关的参数传入。这里pupupwindow的显示界面是用的打气筒把listview加载进来。同时listview条目的布局也用到inflate。因此用到两次打气筒。同时为每一个listview的条目设置条目点击的监听事件,这样在条目被点击时候可以将条目的内容显示在textview中。。Popupwindow的编写另一个关键性的步骤是showAsDropDown,即将要显示在哪个控件下方,偏移量多少出传进来。需要注意的是控件的实际宽高和看到的宽高有一定的误差,只是因为控件的背景用一定的宽度。还有一点就是,按返回键时PopupWindow没法隐藏,给PopupWindow设置一个背景即可解决这个问题,如下:popupWindow.setBackgroundDrawable(new ColorDrawable())。每次显示PopupWindow时都创建一个新的PopupWindow对象,其实可以复用一个PopupWindow对象的。即每次创建前先判断popupwindow是否为空。
- Listiview条目的编写较为定。这里做了两处的优化。一个是服用conterview,开始操作之前判断conterview是否为空。若为空创建一个新的view,否则复用被回收的conterview。另一处的优化是,每一次finviewbyid会消耗大量的内存。因此可以单独定义一个类,存放控件,在cnterview为空时创建一次。每次调用时只需要调用定义类中的控件。还有一点是,要是条目上的删除图标有用还要对删除图片设定一个点击事件。一个小细节是,当listvie条目中存在button及其子类时,会抢占焦点。因此这里删除图片的标签用的是imageview。当然你也可以采取其他方式,比如,在条目的根布局加上这个属性:android:descendantFocusability="blocksDescendants"。
主界面的布局:
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
android:layout_margin="17dp"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.popuwindow.MainActivity"> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"> <EditText
android:id="@+id/et_number"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:hint="输入账号" /> <ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/et_number"
android:layout_alignRight="@id/et_number"
android:layout_alignTop="@id/et_number"
android:background="@null"
android:onClick="showNumberListToggle"
android:src="@mipmap/down_arrow" />
</RelativeLayout>
</RelativeLayout>
listview条目的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="6dp"> <ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/user" /> <TextView
android:id="@+id/tv_numer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_weight="1"
android:text="10000"
android:textSize="18sp" /> <ImageView
android:id="@+id/ib_del"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:src="@mipmap/delete" />
</LinearLayout>
单独写一个listview。
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:cacheColorHint="@null"
android:background="@mipmap/listview_background"
android:descendantFocusability="blocksDescendants">
</ListView>
主程序中的逻辑。
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.PopupWindow; public class MainActivity extends AppCompatActivity {
private EditText et_number;
private PopupWindow popupwindow; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_number = (EditText) findViewById(R.id.et_number);
} public void showNumberListToggle(View view) {
if (popupwindow == null) { //复用popupwindow
View contentView = createContent();
int width = et_number.getWidth() - 4;
int height = 400;
boolean focusable = true;
popupwindow = new PopupWindow(contentView, width, height, focusable);
popupwindow.setBackgroundDrawable(new ColorDrawable());
}
View anchor = et_number;
int xoff = 2;
int yoff = -5;
popupwindow.showAsDropDown(anchor, xoff, yoff);
} private View createContent() {
ListView lv = (ListView) View.inflate(this, R.layout.activity_list, null);
lv.setAdapter(new NumberListAdapter());
lv.setVerticalScrollBarEnabled(false);
lv.setOnItemClickListener(monitemclickListener);
return lv;
} AdapterView.OnItemClickListener monitemclickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String number = (String) parent.getItemAtPosition(position);
et_number.setText(number);
popupwindow.dismiss();
}
};
}
适配器的编写
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; import java.util.ArrayList; /**
* Created by huang on 2016/11/22.
*/
public class NumberListAdapter extends BaseAdapter {
private ArrayList<String> numbers = new ArrayList(); {
for (int i = 0; i < 30; i++) {
numbers.add(10000 + i + "" );
}
} @Override
public int getCount() {
return numbers.size();
} @Override
public Object getItem(int position) {
return numbers.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view;
viewHolder holder;
if(convertView == null){
view = View.inflate(parent.getContext(),R.layout.item_number_list,null);
holder = new viewHolder();
holder.ib_del = (ImageView) view.findViewById(R.id.ib_del);
holder.tv_number = (TextView) view.findViewById(R.id.tv_numer);
view.setTag(holder);
}else{
view = convertView;
holder = (viewHolder)view.getTag();
}
holder.ib_del.setImageResource(R.mipmap.delete);
holder.tv_number.setText(numbers.get(position));
holder.ib_del.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
numbers.remove(position);
notifyDataSetChanged();
}
});
return view;
} static class viewHolder{
TextView tv_number;
ImageView ib_del;
}
}
案例三 viewpager实现轮播图:
功能介绍: 广告条的实现,又被称为轮播图。在手机界面的最上方放置一个ViewPager功能,实现界面的左右滑动。滑动又分为两种,一种是间隔一定的时间自动滑动,同时还支持手势的左右滑动。一个小细节是在轮播图底部放置和图片数量相等的小点,用于表示当前哪个图片被选中。
实现步骤:
1. 布局文件有两部分组成,一个是viewpager,一个是底部的条和小圆点。Viewpager存在于v4包下,因此可兼容到Android1.6。底部的条和小圆点放在一个线性布局中,让放在viewpager的底部,同时文字和圆点为中心位置。这里特别说一下小圆点的实现。小圆点使用shape图做出来的。由于无法再布局文件中获取圆点的个数,因此可以在布局文件中放置一个LinearLayout,然后在java代码中将view对象向该LinearLayout中添加。同时将白点和黑点的状态选择器设置为view的背景。
2. 接下来是viewpager的编写。编写viewpager的关键是写适配器。写一个类继承PagerAdapter,重写其中的方法。Viewpager默认是加载三张图片,屏幕中间一张,屏幕左边和屏幕右边各一张。我们希望轮播图能够循环的播放,因此可以给getcount返回一个足够大的值,初始化轮播图时,将轮播图的初始位置设置在中间,这样就可以实现循环播放。当我们把getcount返回值设为一个很大的值时,在instantiateItem中也要对position进行判断。传入的的position是一个极大的值,但是图片的数量确实有限的,因此可以对position取余,这样就可以把position的位置和图片的数量对应起来。
3. 实现自动播放需要用到消息机制,间隔三秒调用显示下一张图片的方法。显示下一张图片是调用viewpager的setCurrentItem,传入下一个图片的item数。手指滑动时viewpager自身就有的功能,因此不需要再定义。
4. 最后要实现的功能是,viewpager底部的文字和小圆点跟随图片变化。这时候可以设定一个viewpager的监听事件,当图片发生改变时改变textview的值。然后遍历linearlayout的子view(子view中存发的是小圆点),当圆点的序列号和图片的序列号一直是,则选中圆点。当然,这里同样要对position取余,将position转化到于图片大小一致的范围。
主界面的实现:
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.advertisement.MainActivity"> <android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="150dp" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/view_pager"
android:background="@color/trans_balck"
android:gravity="center"
android:orientation="vertical"
android:padding="5dp"> <TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="图片描述"
android:textColor="@android:color/white" /> <LinearLayout
android:id="@+id/ll_dots"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"></LinearLayout>
</LinearLayout>
</RelativeLayout>
状态选择器
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/shape_dot_select"/>
<item android:drawable="@drawable/shape_dot_normal"/>
</selector>
shape图的绘制
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/trans_balck"/>
</shape> <节省空间, 两个写下一起>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/white"/>
</shape>
主程序中的业务逻辑
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView; public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private int[] imageResids = {R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e};
private String[] desc = {
"巩俐不低俗,我就不能低俗",
"扑树又回来啦!再唱经典老歌引万人大合唱",
"揭秘北京电影如何升级",
"乐视网TV版大派送",
"热血屌丝的反杀"
}; private LinearLayout ll_dots;
private TextView tv_desc;
private ViewPager viewpager;
private static final int SHOW_NEXT_PAGE = 0; private Handler handler = new Handler() ; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll_dots = (LinearLayout) findViewById(R.id.ll_dots);
tv_desc = (TextView) findViewById(R.id.tv_desc);
viewpager = (ViewPager) findViewById(R.id.view_pager);
viewpager.setAdapter(new BannerAapter(imageResids));
viewpager.setOnPageChangeListener(listener);
initDot();
changeDotandDesc(0);
viewpager.setCurrentItem(viewpager.getAdapter().getCount() / 2);
handler.postDelayed(mRunnable,3000);
} Runnable mRunnable = new Runnable() {
@Override
public void run() {
shownextpage();
}
};
/**初始化小圆点*/
private void initDot() {
for (int i = 0; i < imageResids.length; i++) {
int _5dp = dp2px(5);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(_5dp, _5dp);
params.leftMargin = _5dp;
View dot = new View(this);
dot.setLayoutParams(params);
dot.setBackgroundResource(R.drawable.select_dot);
ll_dots.addView(dot);
}
}
/**将pd数据转化为px数据*/
private int dp2px(int pd) {
float desity = getResources().getDisplayMetrics().density;
return (int) (pd * desity + 0.5f);
} ViewPager.OnPageChangeListener listener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override
public void onPageSelected(int position) {
changeDotandDesc(position);
} @Override
public void onPageScrollStateChanged(int state) { }
}; public void changeDotandDesc(int position) {
position = position % ll_dots.getChildCount();
tv_desc.setText(desc[position]);
for (int i = 0; i < ll_dots.getChildCount(); i++) {
Log.i(TAG, "changeDotandDesc: " + i+ " " + position);
ll_dots.getChildAt(i).setSelected(i == position);
}
} private void shownextpage() {
int currenItem = viewpager.getCurrentItem();
viewpager.setCurrentItem(currenItem + 1);
handler.postDelayed(mRunnable,3000);
}
}
适配器的编写:
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView; /**
* Created by huang on 2016/11/22.
*/
public class BannerAapter extends PagerAdapter {
private int[] imageResIds; public BannerAapter(int[] imageResIds) {
this.imageResIds = imageResIds;
} @Override
public int getCount() {
return imageResIds.length * 10000 * 100;
} @Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
} @Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageview = new ImageView(container.getContext());
position = position % imageResIds.length;
imageview.setBackgroundResource(imageResIds[position]);
container.addView(imageview);
return imageview;
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((ImageView) object);
}
}
Android中的自定义控件(一)的更多相关文章
- Android中的自定义控件(二)
案例四: 自定义开关 功能介绍:本案例实现的功能是创建一个自定义的开关,可以自行决定开关的背景.当滑动开关时,开关的滑块可跟随手指移动.当手指松开后,滑块根据开关的状态,滑到最右边或者滑到 ...
- Android中创建自定义控件
1.创建一个TitleLayout继承LinearLayout: //创建自定义控件 public class TitleLayout extends LinearLayout { private f ...
- Android中仿IOS提示框的实现
前言 在Android开发中,我们有时需要实现类似IOS的对话框.今天我就来总结下,如何通过自定义的开发来实现类似的功能. 自定义Dialog 我们知道Android中最常用的对话框就是Dialog及 ...
- Android中自定义属性(attrs.xml,TypedArray的使用)
做Android布局是件很享受的事,这得益于他良好的xml方式.使用xml可以快速有效的为软件定义界面.可是有时候我们总感觉官方定义的一些基本组件不够用,自定义组件就不可避免了.那么如何才能做到像官方 ...
- (转)android中颜色矩阵colormatrix
原文地址:http://www.cnblogs.com/menlsh/archive/2013/02/03/2890888.html 在Android中,对图像进行颜色方面的处理,如黑白老照片.泛黄旧 ...
- Android中的动态加载机制
在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本 ...
- Android使用AttributeSet自定义控件的方法
所谓自定义控件(或称组件)也就是编写自己的控件类型,而非Android中提供的标准的控件,如TextView,CheckBox等等.不过自定义的控件一般也都是从标准控件继承来的,或者是多种控件组合,或 ...
- 荐 android 如何打包自定义控件(转)
荐 android 如何打包自定义控件(转) 目录[-] 方式一:将项目打包成jar包 方式二:项目作为一个library 设计自定义的控件对android开发人员来说,是家常便饭了,但是多次做项 ...
- Android开发技巧——自定义控件之增加状态
Android开发技巧--自定义控件之增加状态 题外话 这篇本该是上周四或上周五写的,无奈太久没写博客,前几段把我的兴头都用完了,就一拖再拖,直到今天.不想把这篇拖到下个月,所以还是先硬着头皮写了. ...
随机推荐
- 我的MYSQL学习心得(十一) 视图
我的MYSQL学习心得(十一) 视图 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...
- 前端构建大法 Gulp 系列 (四):gulp实战
前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gulp专家 前 ...
- 【完全开源】知乎日报UWP版:项目结构说明、关键源代码解释
目录 说明 项目结构 关键代码 演示视频 说明 上一篇博客将源码放出来了,但是并没有做过多的介绍,所以如果自己硬看可能需要花费很长的时间,尤其这些代码并不是自己写的.项目不算复杂但是也不算简单,这篇文 ...
- ASP.NET MVC 5 Web编程5 -- 页面传值的方式
本篇文章将讲述MVC的页面传值方式,具体包括:后端向前端传值(Controller向View传值):前端向后端传值(View向Controller传值):Action与Action之间的传值. 回顾 ...
- [转]keil使用详解
第一节 系统概述 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上.结构性.可读性.可维护性上有明显的优势,因而易学易用.用过 ...
- [译]ZOOKEEPER RECIPES-Barriers
Barrier 在分布式系统中常使用Barrier来阻塞进程,当满足一定条件后再恢复进行后续操作.Barrier在Zookeeper中可以通过设计一个Barrier节点来实现.Barrier 节点存在 ...
- 使用google 语言 api 来实现整个网站的翻译
---恢复内容开始--- 使用google 语言 api 来实现整个网站的翻译,这时我们可以利用免费的google api来做处理来实现多语言的功能. 放在 HTML 文件中 <div id=& ...
- Html<a>标签href的困惑记载
近日,在工作中遇到一个小问题(给手游平台做些网页活动,其中牵涉到一个按钮链接,就习以为常的用了A标签,Click响应之后走一段js代码逻辑-弹出一个分享微信弹框.Chrome和Android平台都没问 ...
- JSP页面跳转的几种实现方法
使用href超链接标记 客户端跳转 使用JavaScript 客户端跳转 提交表单 客户端跳转 使用response ...
- springmvc环境搭建以及常见问题解决
1.新建maven工程 a) 打开eclipse,file->new->project->Maven->Maven Project b) 下一步 c) 选择创建的工程为 ...