首页 文章 精选 留言 我的

精选列表

搜索[ui],共10002篇文章
优秀的个人博客,低调大师

Android--UI之ImageSwitcher

前言 这篇博客来聊一聊AndroidUI开发中ImageSwitcher控件的使用。ImageSwitcher控件与ImageView类似,都可以用于显示图片,但是ImageSwitcher通过名字可以看出,主要是用于多张图片的切换显示。在本篇博客中,会介绍ImageSwitcher控件的基本属性的设置以及常用方法的调用。在最后会通过一个示例Demo来展示本篇博客中讲到的一些内容。 ImageSwitcher ImageSwitcher是一个图片切换器,它间接继承自FrameLayout类,和ImageView相比,多了一个功能,那就是它说显示的图片切换时,可以设置动画效果,类似于淡进淡出效果,以及左进右出滑动等效果。 既然ImageSwitcher是用来显示图片的控件,AndroidAPI为我们提供了三种不同方法来设定不同的图像来源,方法有: setImageDrawable(Drawable):指定一个Drawable对象,用来给ImageSwitcher显示。 setImageResource(int):指定一个资源的ID,用来给ImageSwitcher显示。 setImageURL(URL):指定一个URL地址,用来给ImageSwitcher显示URL指向的图片资源。 动画效果设定 上面介绍到,ImageSwitcher可以设置图片切换时,动画的效果。对于动画效果的支持,是因为它继承了ViewAnimator类,这个类中定义了两个属性,用来确定切入图片的动画效果和切出图片的动画效果: android:inAnimation:切入图片时的效果。 android:outAnimation:切出图片时的效果。 以上两个属性如果在XML中设定的话,当然可以通过XML资源文件自定义动画效果,但是如果只是想使用Android自带的一些简单的效果的话,需要设置参数为“@android:anim/AnimName”来设定效果,其中AnimName为指定的动画效果。如果在代码中设定的话,可以直接使用setInAnimation()和setOutAnimation()方法。它们都传递一个Animation的抽象对象,Animation用于描述一个动画效果,一般使用一个AnimationUtils的工具类获得。对于动画效果,不是本片博客的重点,关于Android的动画效果,以后再详细讲解。 对于动画效果,一般定义在android.R.anim类中,它是一个final类,以一些int常量的形式,定义的样式,这里仅仅介绍两组样式,淡进淡出效果,以及左进右出滑动效果,如果需要其他效果,可以查阅官方文档。 fede_in:淡进。 fade_out:淡出 slide_in_left:从左滑进。 slide_out_right:从右滑出。 一般使用的话,通过这些常量名称就可以看出是什么效果,这里并不是强制Xxx_in_Xxx就一定对应了setInAnimation()方法,但是一般如果不成组设定的话,效果会很丑,建议还是成组的对应In和Out设定效果。 ViewFactory 在使用ImageSwitcher的时候,有一点特别需要注意的,需要通过setFactory()方法为它设置一个ViewSwitcher.ViewFactory接口,设置这个ViewFactory接口时需要实现makeView()方法,该方法通常会返回一个ImageView,而ImageSwitcher则负责显示这个ImageView。如果不设定ViewFactory的话,ImageSwitcher将无法使用。通过官方文档了解到,setFactory()方法被声明在ViewSwitcher类中,而ImageSwitcher直接继承自ViewSwitcher类。ViewSwitcher的功能与ImageSwitcher类似,只是ImageSwitcher用于展示图片,而ViewSwitcher用于展示一些View视图。 可以这么理解,通过ViewFactory中的makeView()方法返回一个新的View视图,用来放入ViewSwitcher中展示,而对于ImageSwitcher而言,这里通常返回的是一个ImageView。 示例程序 下面通过一个Demo来说明上面讲到的内容。在示例中定义一个ImageSwitcher和两个Button,这两个按钮分别控制着图像的上一张、下一张显示,当然,在资源中必须存在这几个待切换的图片文件。。 布局代码: 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:paddingBottom="@dimen/activity_vertical_margin" 6 android:paddingLeft="@dimen/activity_horizontal_margin" 7 android:paddingRight="@dimen/activity_horizontal_margin" 8 android:paddingTop="@dimen/activity_vertical_margin" 9 tools:context=".MainActivity" android:orientation="vertical"> 10 11 <ImageSwitcher 12 android:id="@+id/imageSwitcher1" 13 android:layout_width="fill_parent" 14 android:layout_height="150dp" 15 /> 16 <Button 17 android:id="@+id/btnadd" 18 android:layout_width="fill_parent" 19 android:layout_height="wrap_content" 20 android:text="上一张" /> 21 <Button 22 android:id="@+id/btnSub" 23 android:layout_width="fill_parent" 24 android:layout_height="wrap_content" 25 android:text="下一张" /> 26 </LinearLayout> 实现代码: 1 package com.bgxt.imageswitcherDemo; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.os.Bundle; 7 import android.app.Activity; 8 import android.graphics.drawable.Drawable; 9 import android.view.Menu; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.view.animation.Animation; 13 import android.view.animation.AnimationUtils; 14 import android.widget.Button; 15 import android.widget.ImageSwitcher; 16 import android.widget.ImageView; 17 import android.widget.ViewSwitcher.ViewFactory; 18 19 public class MainActivity extends Activity { 20 private Button btnAdd, btnSub; 21 private ImageSwitcher imageSwitcher; 22 private int index = 0; 23 private List<Drawable> list; 24 25 @Override 26 protected void onCreate(Bundle savedInstanceState) { 27 super.onCreate(savedInstanceState); 28 setContentView(R.layout.activity_main); 29 putData(); 30 imageSwitcher = (ImageSwitcher) findViewById(R.id.imageSwitcher1); 31 btnAdd = (Button) findViewById(R.id.btnadd); 32 btnSub = (Button) findViewById(R.id.btnSub); 33 btnAdd.setOnClickListener(myClick); 34 btnSub.setOnClickListener(myClick); 35 36 //通过代码设定从左缓进,从右换出的效果。 37 imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_in_left)); 38 imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_out_right)); 39 imageSwitcher.setFactory(new ViewFactory() { 40 41 @Override 42 public View makeView() { 43 // makeView返回的是当前需要显示的ImageView控件,用于填充进ImageSwitcher中。 44 return new ImageView(MainActivity.this); 45 } 46 }); 47 imageSwitcher.setImageDrawable(list.get(0)); 48 } 49 50 @Override 51 public boolean onCreateOptionsMenu(Menu menu) { 52 // Inflate the menu; this adds items to the action bar if it is present. 53 getMenuInflater().inflate(R.menu.main, menu); 54 return true; 55 } 56 57 private View.OnClickListener myClick = new OnClickListener() { 58 59 @Override 60 public void onClick(View v) { 61 switch (v.getId()) { 62 case R.id.btnadd: 63 index--; 64 if(index<0) 65 { 66 //用于循环显示图片 67 index=list.size()-1; 68 } 69 //设定ImageSwitcher显示新图片 70 imageSwitcher.setImageDrawable(list.get(index)); 71 break; 72 73 case R.id.btnSub: 74 index++; 75 if(index>=list.size()) 76 { 77 //用于循环显示图片 78 index=0; 79 } 80 imageSwitcher.setImageDrawable(list.get(index)); 81 break; 82 } 83 } 84 }; 85 86 private void putData() { 87 //填充图片的Drawable资源数组 88 list = new ArrayList<Drawable>(); 89 list.add(getResources().getDrawable(R.drawable.bmp1)); 90 list.add(getResources().getDrawable(R.drawable.bmp2)); 91 list.add(getResources().getDrawable(R.drawable.bmp3)); 92 list.add(getResources().getDrawable(R.drawable.bmp4)); 93 list.add(getResources().getDrawable(R.drawable.bmp5)); 94 } 95 } 效果展示: 源码下载 总结 本篇博客主要讲解了ImageSwitcher的使用方式,而对于其父类ViewSwitcher的使用,大致上与ImageSwitcher相似,只是填充的内容不同而已,一般了解了ImageSwitcher的使用,再看ViewSwitcher就很好理解,以后有时间再详细讲解ViewSwitcher的使用。 本文转自承香墨影博客园博客,原文链接:http://www.cnblogs.com/plokmju/p/android_ImageSwitcher.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android:UI控件ViewPager,notifyDataSetChanged

ViewPager的使用: 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 public class MainActivity extends Activity { /* *XML添加viewpager方法: *<android.support.v4.view.ViewPager *android:id="@+id/viewPager" *android:layout_width="match_parent" *android:layout_height="match_parent"/> */ int []ImageIds= new int [] {R.drawable.guide_daily_brand,R.drawable.guide_item_detail_1,R.drawable.guide_item_detail_2,R.drawable.guide_multi_shop_detail, R.drawable.guide_pic_mode,R.drawable.guide_timeline_filter}; private ArrayList<View>mViewList= new ArrayList<View>(); @Override protected void onCreate(BundlesavedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewPagerviewPager=(ViewPager)findViewById(R.id.viewPager); viewPager.setAdapter( new PagerAdapter() { @Override public ObjectinstantiateItem(Viewcontainer, int position) { //第一页和最后一页只创建保留两个view来复用,中间则保留三个view LayoutInflaterinflater=getLayoutInflater(); Viewlayout=inflater.inflate(R.layout.pager_item, null ); //将View加入到容器和container里面,不加判断会造成泄漏 if (mViewList.size()<ImageIds.length) { mViewList.add(layout); } ((ViewPager)container).addView(layout, 0 ); layout.setBackgroundResource(ImageIds[position]); return layout; } @Override public void destroyItem(Viewcontainer, int position,Objectobject) { //此处的position与上面的并不相等,会自动销毁不在当前页左右的view ((ViewPager)container).removeView(mViewList.get(position)); } @Override public boolean isViewFromObject(Viewarg0,Objectarg1) { return arg0==arg1; //判断对象与类型 } @Override public int getCount() { return ImageIds.length; } }); } @Override public boolean onCreateOptionsMenu(Menumenu) { getMenuInflater().inflate(R.menu.main,menu); return true ; } } 其他笔记: 1.viewpager切换时容易造成oom问题 1 2 3 4 5 6 mViewPager=(ViewPager)findViewById(R.id.photogallery_viewpager); mAdapter= new PhotoGalleryAdapter(); //限制view的数量,减少view缓存,在setAdapter之前使用 mViewPager.setOffscreenPageLimit( 3 ); mViewPager.setAdapter(mAdapter); mViewPager.setCurrentItem(mPagerSelected); 2.两种removeview方法 1 2 3 4 5 6 @Override public void destroyItem(Viewcontainer, int position,Objectobject) { //((ViewPager)container).removeView((View)object); ((ViewPager)container).removeView(mViewList.get(position)); } 3.关于notifyDataSetChanged()方法无法及时更新的问题解决方法 (1)销毁ViewItem时要使用以下方法: 1 2 3 4 5 6 @Override public void destroyItem(Viewcontainer, int position,Objectobject) { //((ViewPager)container).removeView(mViewList.get(position)); ((ViewPager)container).removeView((View)object); } 参考资料:http://www.myexception.cn/android/417891.html (2)重写notifyDataSetChanged()和getItemPosition(Object object)方法,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private int mChildCount= 0 ; @Override public void notifyDataSetChanged() { mChildCount=getCount(); super .notifyDataSetChanged(); } @Override public int getItemPosition(Objectobject) { if (mChildCount> 0 ) { mChildCount--; return POSITION_NONE; } return super .getItemPosition(object); } 参考资料:http://www.cnblogs.com/maoyu417/p/3740209.html 附相关注释: 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 进入viewpager,我们终于找到了viewpager中控制数据变更的重点方法dataSetChanged,这个方法如下: void dataSetChanged(){ //Thismethodonlygetscalledifourobserverisattached,somAdapterisnon-null. boolean needPopulate=mItems.size()<mOffscreenPageLimit* 2 + 1 && mItems.size()<mAdapter.getCount(); int newCurrItem=mCurItem; boolean isUpdating= false ; for ( int i= 0 ;i<mItems.size();i++){ final ItemInfoii=mItems.get(i); final int newPos=mAdapter.getItemPosition(ii.object); if (newPos==PagerAdapter.POSITION_UNCHANGED){ continue ; } if (newPos==PagerAdapter.POSITION_NONE){ mItems.remove(i); i--; if (!isUpdating){ mAdapter.startUpdate( this ); isUpdating= true ; } mAdapter.destroyItem( this ,ii.position,ii.object); needPopulate= true ; if (mCurItem==ii.position){ //Keepthecurrentiteminthevalidrange newCurrItem=Math.max( 0 ,Math.min(mCurItem,mAdapter.getCount()- 1 )); needPopulate= true ; } continue ; } if (ii.position!=newPos){ if (ii.position==mCurItem){ //Ourcurrentitemchangedposition.Followit. newCurrItem=newPos; } ii.position=newPos; needPopulate= true ; } } if (isUpdating){ mAdapter.finishUpdate( this ); } Collections.sort(mItems,COMPARATOR); if (needPopulate){ //Resetourknownpagewidths;populatewillrecomputethem. final int childCount=getChildCount(); for ( int i= 0 ;i<childCount;i++){ final Viewchild=getChildAt(i); final LayoutParamslp=(LayoutParams)child.getLayoutParams(); if (!lp.isDecor){ lp.widthFactor= 0 .f; } } setCurrentItemInternal(newCurrItem, false , true ); requestLayout(); } } 重点看这样一行代码: final int newPos=mAdapter.getItemPosition(ii.object); if (newPos==PagerAdapter.POSITION_UNCHANGED){ continue ; } 官方对getItemPosition()的解释是: Calledwhenthehostviewisattemptingtodetermine if anitem’spositionhaschanged.ReturnsPOSITION_UNCHANGED if thepositionofthegivenitemhasnotchangedorPOSITION_NONE if theitemisnolongerpresentintheadapter. The default implementationassumesthatitemswillneverchangepositionandalwaysreturnsPOSITION_UNCHANGED. 意思是如果item的位置如果没有发生变化,则返回POSITION_UNCHANGED。如果返回了POSITION_NONE,表示该位置的item已经不存在了。默认的实现是假设item的位置永远不会发生变化,而返回POSITION_UNCHANGED 解决方案: 所以我们可以尝试着修改适配器的写法,覆盖getItemPosition()方法,当调用notifyDataSetChanged时,让getItemPosition方法人为的返回POSITION_NONE,从而达到强迫viewpager重绘所有item的目的。 本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1224648,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android--UI之ProgressBar

前言 开门见山,开篇明意。这篇博客主要讲解一下Android中ProgressBar控件以及间接继承它的两个子控件SeekBar、RatingBar的基本用法,因为其有继承关系,存在一些共有特性,所以在一篇博客中讲解。下面先简单描述一下这三个控件: ProgressBar是一个进度条控件,一般在需要做某个比较耗时的操作的时候,向用户展示执行进度,以免用户以为已经失去响应。 SeekBar是一个拖动条控件,拖动条通过滑块表示数值,而用户可以在一定范围内拖动这个滑块而改变其数值。 RatingBar是一个星级评分控件,向用户展示一个评分样式的控件,用户可以选择星级来为其评分。 ProgressBar ProgressBar,进度条,是AndroidUI界面中一个非常实用的组件,通常用于向用户显示某个耗时操作完成的百分比。因此它需要动态的显示进度,从而避免长时间的执行某个耗时的操作,而让用户感觉程序失去了相应,从而提高界面的友好性。 从官方文档上看,为了适应不同的应用环境,Android内置了几种风格的进度条,可以通过Style属性设置ProgressBar的风格。支持如下属性,后面在示例中会一一展示: @android:style/Widget.ProgressBar.Horizontal:水平进度条(可以显示刻度,常用)。 @android:style/Widget.ProgressBar.Small:小进度条。 @android:style/Widget.ProgressBar.Large:大进度条。 @android:style/Widget.ProgressBar.Inverse:不断跳跃、旋转画面的进度条。 @android:style/Widget.ProgressBar.Large.Inverse:不断跳跃、旋转动画的大进度条。 @android:style/Widget.ProgressBar.Small.Inverse:不断跳跃、旋转动画的小进度条。 只有Widget.ProgressBar.Horizontal风格的进度条,才可以设置进度的递增,其他的风格展示为一个循环的动画,而设置Widget.ProgressBar.Horizontal风格的进度条,需要用到一些属性设置递增的进度,这些属性都有对应的setter、getter方法,这些属性如下: android:max:设置进度的最大值。 android:progress:设置当前第一进度值。 android:secondaryProgress:设置当前第二进度值。 android:visibility:设置是否显示,默认显示。 对于Widget.ProgressBar.Horizontal风格的进度条而言,在代码中动态设置移动量,除了可以使用setProgress(int)方法外,Android还为我们提供了另外一个incrementProgressBy(int)方法,它与setProgress(int)的根本区别在于,setProgress(int)是直接设置当前进度值,而incrementProgressBy(int)是设置当前进度值的增量(正数为增,负数为减)。与setProgress(int)和incrementProgressBy(int)对应的还有setSecondaryProgress(int)和incrementSecondaryProgressBy(int)方法,用于设置第二进度值。 下面通过一个示例,来讲解一下上面的style设置样式的展示想过,以及动态控制进度条增减的实现。 布局代码: 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <TextView 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:text="android:style/Widget.ProgressBar.Small" /> 11 12 <ProgressBar 13 style="@android:style/Widget.ProgressBar.Small" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" /> 16 17 <TextView 18 android:layout_width="wrap_content" 19 android:layout_height="wrap_content" 20 android:text="android:style/Widget.ProgressBar.Large" /> 21 22 <ProgressBar 23 android:id="@+id/pbLarge" 24 style="@android:style/Widget.ProgressBar.Large" 25 android:layout_width="wrap_content" 26 android:layout_height="wrap_content" /> 27 28 <TextView 29 android:layout_width="wrap_content" 30 android:layout_height="wrap_content" 31 android:text="android:style/Widget.ProgressBar.Inverse" /> 32 33 <ProgressBar 34 style="@android:style/Widget.ProgressBar.Inverse" 35 android:layout_width="wrap_content" 36 android:layout_height="wrap_content" /> 37 38 <TextView 39 android:layout_width="wrap_content" 40 android:layout_height="wrap_content" 41 android:text="android:style/Widget.ProgressBar.Small.Inverse" /> 42 43 <ProgressBar 44 style="@android:style/Widget.ProgressBar.Small.Inverse" 45 android:layout_width="wrap_content" 46 android:layout_height="wrap_content" /> 47 48 <TextView 49 android:layout_width="wrap_content" 50 android:layout_height="wrap_content" 51 android:text="android:style/Widget.ProgressBar.Large.Inverse" /> 52 53 <ProgressBar 54 style="@android:style/Widget.ProgressBar.Large.Inverse" 55 android:layout_width="wrap_content" 56 android:layout_height="wrap_content" /> 57 58 <TextView 59 android:layout_width="wrap_content" 60 android:layout_height="wrap_content" 61 android:text="android:style/Widget.ProgressBar.Horizontal" /> 62 63 <ProgressBar 64 android:id="@+id/pbHor" 65 style="@android:style/Widget.ProgressBar.Horizontal" 66 android:layout_width="match_parent" 67 android:layout_height="wrap_content" 68 android:max="100" 69 android:progress="20" 70 android:secondaryProgress="60" /> 71 72 <LinearLayout 73 android:layout_width="match_parent" 74 android:layout_height="match_parent" 75 android:orientation="horizontal" > 76 <!-- 设置一个按钮控制水平进度的递增 --> 77 <Button 78 android:id="@+id/btnAdd" 79 android:layout_width="wrap_content" 80 android:layout_height="wrap_content" 81 android:text=" + " /> 82 <!-- 设置一个按钮控制水平进度的递减 --> 83 <Button 84 android:id="@+id/btnReduce" 85 android:layout_width="wrap_content" 86 android:layout_height="wrap_content" 87 android:layout_marginLeft="30dp" 88 android:text=" - " /> 89 <!-- 设置一个按钮控制Style为large的进度显示与隐藏 --> 90 <Button 91 android:id="@+id/btnVisible" 92 android:layout_width="wrap_content" 93 android:layout_height="wrap_content" 94 android:layout_marginLeft="30dp" 95 android:text="VisibleLarge" /> 96 </LinearLayout> 97 98 </LinearLayout> 实现代码: 1 package com.bgxt.progressbarseriesdemo; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.view.View; 6 import android.view.View.OnClickListener; 7 import android.widget.Button; 8 import android.widget.ProgressBar; 9 10 public class ProgressBarActivity extends Activity { 11 12 private Button btnAdd, btnReduce, btnVisible; 13 private ProgressBar pbHor, pbLarge; 14 15 @Override 16 protected void onCreate(Bundle savedInstanceState) { 17 super.onCreate(savedInstanceState); 18 setContentView(R.layout.activity_progressbar); 19 20 btnAdd = (Button) findViewById(R.id.btnAdd); 21 btnReduce = (Button) findViewById(R.id.btnReduce); 22 btnVisible = (Button) findViewById(R.id.btnVisible); 23 pbHor = (ProgressBar) findViewById(R.id.pbHor); 24 pbLarge = (ProgressBar) findViewById(R.id.pbLarge); 25 26 btnAdd.setOnClickListener(mathClick); 27 btnReduce.setOnClickListener(mathClick); 28 btnVisible.setOnClickListener(new View.OnClickListener() { 29 30 @Override 31 public void onClick(View v) { 32 // 判断Large进度条是否显示,显示则隐藏,隐藏则显示 33 if (pbLarge.getVisibility() == View.VISIBLE) { 34 pbLarge.setVisibility(View.GONE); 35 } else { 36 pbLarge.setVisibility(View.VISIBLE); 37 } 38 39 } 40 }); 41 } 42 43 private View.OnClickListener mathClick = new OnClickListener() { 44 45 @Override 46 public void onClick(View v) { 47 switch (v.getId()) { 48 case R.id.btnAdd: 49 // 如果是增加按钮,因为进度条的最大值限制在100,第一刻度限制在90. 50 // 在此限度内,以1.2倍递增 51 // 使用setProgress() 52 if (pbHor.getProgress() < 90) { 53 pbHor.setProgress((int) (pbHor.getProgress() * 1.2)); 54 } 55 if (pbHor.getSecondaryProgress() < 100) { 56 pbHor.setSecondaryProgress((int) (pbHor 57 .getSecondaryProgress() * 1.2)); 58 } 59 break; 60 case R.id.btnReduce: 61 // 如果是增加按钮,因为进度条的最大值限制在100,第一刻度限制在10.第二刻度限制在20 62 // 在此限度内,以10点为基数进行递减。 63 // 使用incrementXxxProgressBy(int) 64 if (pbHor.getProgress() > 10) { 65 pbHor.incrementProgressBy(-10); 66 } 67 if (pbHor.getSecondaryProgress() > 20) { 68 pbHor.incrementSecondaryProgressBy(-10); 69 } 70 break; 71 } 72 } 73 }; 74 75 } 展示效果:初始--递增--隐藏 SeekBar SeekBar,拖动条控件 ,间接继承自ProgressBar,所以与进度条类似,但是进度条采用颜色填充来表名进度完成的程度,而拖动条则通过滑动的位置来标识数值。 SeekBar继承自ProgressBar,所以也继承了它的属性设置,上面介绍的一些属性在SeekBar中都可以用到。因为SeekBar涉及到一个滑块的概念,所以新增了属性android:thumb来通过设置一个Drawable对象,指定自定义滑块的外观,当然如果不设定也可以默认使用Android自带的风格。 当用户按住滑块进行滑动的时候,会触发一个SeekBar.OnSeekBarChangeListener事件,这是一个接口,需要开发人员实现三个方法: onProgressChanged(SeekBar seekBar,int progress,boolean fromUser):滑块在移动的时候响应。seekBar为触发事件的SeekBar控件,progress为当前SeekBar的滑块数值,fromUser为是否用户拖动产生的响应。 onStartTrackingTouch(SeekBar seekBar):滑块开始移动的时候响应。 onStopTrackingTouch(SeekBar seekBar):滑块结束移动的时候相应。 下面通过一个示例来讲解一下SeekBar的基本用法。 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 <TextView 7 8 android:id="@+id/textview1" 9 android:layout_width="match_parent" 10 android:layout_height="30dp" /> 11 12 <TextView 13 android:id="@+id/textview2" 14 android:layout_width="match_parent" 15 android:layout_height="30dp" /> 16 17 <SeekBar 18 android:layout_marginTop="30dp" 19 android:id="@+id/seekbar1" 20 android:layout_width="match_parent" 21 android:layout_height="wrap_content" 22 android:max="100" 23 android:progress="30" /> 24 <!--设置一个拖动条,滑块为定义的bar图片--> 25 <SeekBar 26 android:layout_marginTop="30dp" 27 android:id="@+id/seekbar2" 28 android:layout_width="match_parent" 29 android:layout_height="wrap_content" 30 android:max="100" 31 android:progress="20" 32 android:thumb="@drawable/bar" 33 android:secondaryProgress="80" /> 34 35 </LinearLayout> 实现代码: 1 package com.bgxt.progressbarseriesdemo; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.widget.SeekBar; 6 import android.widget.TextView; 7 import android.widget.SeekBar.OnSeekBarChangeListener; 8 9 public class SeekBarActivity extends Activity { 10 private TextView textview1, textview2; 11 private SeekBar seekbar1, seekbar2; 12 @Override 13 protected void onCreate(Bundle savedInstanceState) { 14 // TODO Auto-generated method stub 15 super.onCreate(savedInstanceState); 16 setContentView(R.layout.activity_seekbar); 17 18 textview1 = (TextView) findViewById(R.id.textview1); 19 textview2 = (TextView) findViewById(R.id.textview2); 20 seekbar1 = (SeekBar) findViewById(R.id.seekbar1); 21 seekbar2 = (SeekBar) findViewById(R.id.seekbar2); 22 23 seekbar1.setOnSeekBarChangeListener(seekBarChange); 24 seekbar2.setOnSeekBarChangeListener(seekBarChange); 25 } 26 private OnSeekBarChangeListener seekBarChange = new OnSeekBarChangeListener() { 27 28 @Override 29 public void onStopTrackingTouch(SeekBar seekBar) { 30 if (seekBar.getId() == R.id.seekbar1) { 31 textview1.setText("seekbar1停止拖动"); 32 } else { 33 textview1.setText("seekbar2停止拖动"); 34 } 35 } 36 37 @Override 38 public void onStartTrackingTouch(SeekBar seekBar) { 39 if (seekBar.getId() == R.id.seekbar1) { 40 textview1.setText("seekbar1开始拖动"); 41 } else { 42 textview1.setText("seekbar2开始拖动"); 43 } 44 } 45 46 @Override 47 public void onProgressChanged(SeekBar seekBar, int progress, 48 boolean fromUser) { 49 if (seekBar.getId() == R.id.seekbar1) { 50 textview2.setText("seekbar1的当前位置是:" + progress); 51 } else { 52 textview2.setText("seekbar2的当前位置是:" + progress); 53 } 54 55 } 56 }; 57 } 效果展示: RatingBar RatingBar,星级评分控件,RatingBar与SeekBar的用法非常相似,并且具有相同的父类AbsSeekBar,AbsSeekbar又继承自ProgressBar。而RatingBar与SeekBar最大的区别在于:RatingBar通过星形图标来表示进度。 RatingBar扩展了AbsSeekbar,所以新增了一些固有的属性,也屏蔽了一些无用的属性,如在RatingBar中就不存在第二进度的概念,新增的属性有如下几个: android:isIndicator:设置是否允许用户修改,true为不允许,默认为false,允许。 android:numStars:设置评分控件一共展示多少个星星,默认5个。 android:rating:设置初始默认星级数。 android:stepSize:设置每次需要修改多少个星级。 对于RatingBar而言,当改变其星级选项的时候,会触发一个RatingBar.OnRatingBarChangeListener事件,这是一个接口,需要实现其中的onRatingChanged(RatingBar ratingBar,float rating,boolean fromUser)方法,其中ratingBar表示触发事件的控件,rating表示当前的星级,fromUser表示是否用户触发的修改事件。 在这里需要注意的一点就是,因为继承关系,RatingBar也有Progress属性,但是还有另外一个属性rating表示星级。这两个属性代表的意义是有区别的,区别在于Progress属性针对的是Max属性设置的值而言的,而rating是单纯的表示第几颗星。 下面通过一个示例来展示一下评分控件的基本使用。 布局代码: 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <TextView 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" 10 android:text="评分控件的使用" 11 android:textSize="20dp" /> 12 13 <RatingBar 14 android:id="@+id/rbRating" 15 android:layout_width="wrap_content" 16 android:layout_height="wrap_content" /> 17 18 <RatingBar 19 android:id="@+id/rbRating1" 20 android:layout_width="wrap_content" 21 android:layout_height="wrap_content" 22 android:isIndicator="false" 23 android:max="100" 24 android:numStars="4" 25 android:rating="2.5" 26 android:stepSize="0.5" /> 27 28 </LinearLayout> 实现代码: 1 package com.bgxt.progressbarseriesdemo; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.widget.RatingBar; 6 import android.widget.RatingBar.OnRatingBarChangeListener; 7 import android.widget.Toast; 8 9 public class RatingBarActivity extends Activity implements OnRatingBarChangeListener { 10 11 private RatingBar rbRating,rbRating1; 12 @Override 13 protected void onCreate(Bundle savedInstanceState) { 14 super.onCreate(savedInstanceState); 15 setContentView(R.layout.activity_ratingbar); 16 rbRating=(RatingBar)findViewById(R.id.rbRating); 17 rbRating1=(RatingBar)findViewById(R.id.rbRating1); 18 //手动设置第一个RatingBar的属性值 19 rbRating.setMax(100); 20 rbRating.setProgress(20); 21 rbRating.setOnRatingBarChangeListener(this); 22 rbRating1.setOnRatingBarChangeListener(this); 23 } 24 @Override 25 public void onRatingChanged(RatingBar ratingBar, float rating, 26 boolean fromUser) { 27 //分别显示Progress属性和rating属性的不同 28 int progress=ratingBar.getProgress(); 29 Toast.makeText(RatingBarActivity.this, "progress:"+progress+" rating :"+rating,Toast.LENGTH_SHORT).show(); 30 } 31 32 } 展示效果: 示例代码下载 总结 以上就详细说明了ProgressBar控件以及其两个子控件的用法,此处不包括控件样式的设置,对于控件的展示效果,以后再进行详解。 本文转自承香墨影博客园博客,原文链接:http://www.cnblogs.com/plokmju/p/android_ProgressBar.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android--UI之EditText

前言 上一篇博客介绍了Android的TextView控件,这篇博客来说一下EditText控件。EditText为一个文本控件,提供了文本输入的功能,而且继承自TextView,可以理解为可以输入的TextView。因为继承的关系,很多TextView可以用到的方法,在EditText都可以用到。 EditText 对于EditText,在很多平台上都有用到,最大的用处就是供用户输入一些信息,所以主要的方法就两个: setText():设置TextView控件中显示的内容。 getText() 获取TextView控件中显示的内容。 示例程序 现在通过两个示例程序,来讲解一下EditText的使用。 第一个例子,在EditText中插入表情图片,无论是开发任何系统,这个都是常用的实现。在编码之前,需要找到一些表情图片的资源,我这里就随机找了十张图片,注意资源文件的文件名必须是小写的,放在/res/drawable文件夹下。这样在清单文件R中,就可以看到与Drawable资源对于的资源清单ID,对于在清单文件中的资源,可以通过R类访问,但是访问到的为一个int类型的资源ID,如果需要访问详细内容,需要使用getResource()方法访问到所有的资源,在其中有特定资源的访问方法。关于资源清单文件R,以后再进行详细讲解。 在Android中,使用图片资源会用到一个Bitmap的类,此类代表一个位图资源,是一个final类,需要使用BitmapFactory类的静态方法decodeXxx()转化获得,此静态方法有多种重载模式,可以适应不同的资源来源。 下面直接上代码,对于布局而言,很简单的只有两个控件: 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <EditText 8 android:id="@+id/edImage" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:layout_marginTop="20dp"/> 12 13 <Button 14 android:id="@+id/btnInImg" 15 android:text="添加表情" 16 android:layout_width="match_parent" 17 android:layout_height="wrap_content"/> 18 </LinearLayout> 实现InImageActivity.java代码: 1 package cn.bgxt.androiduiedittext; 2 3 import java.util.Random; 4 5 import android.app.Activity; 6 import android.graphics.Bitmap; 7 import android.graphics.BitmapFactory; 8 import android.graphics.drawable.Drawable; 9 import android.os.Bundle; 10 import android.text.Spannable; 11 import android.text.SpannableString; 12 import android.text.style.ImageSpan; 13 import android.view.View; 14 import android.widget.Button; 15 import android.widget.EditText; 16 17 public class InImageActivity extends Activity { 18 19 private Button btnInImg; 20 private EditText edImage; 21 //获取Drawable资源的Id数组 22 private final int[] DRAW_IMG_ID= 23 { 24 R.drawable.image0, 25 R.drawable.image1, 26 R.drawable.image2, 27 R.drawable.image3, 28 R.drawable.image4, 29 R.drawable.image5, 30 R.drawable.image6, 31 R.drawable.image7, 32 R.drawable.image8, 33 R.drawable.image9 34 }; 35 public InImageActivity() { 36 // TODO Auto-generated constructor stub 37 } 38 39 @Override 40 protected void onCreate(Bundle savedInstanceState) { 41 super.onCreate(savedInstanceState); 42 setContentView(R.layout.edittextinimg_activity); 43 44 btnInImg=(Button)findViewById(R.id.btnInImg); 45 edImage=(EditText)findViewById(R.id.edImage); 46 47 btnInImg.setOnClickListener(new View.OnClickListener() { 48 @Override 49 public void onClick(View v) { 50 // 参数一个0-9的随机数 51 int random=new Random().nextInt(9); 52 //通过bitmapFactory获得位图资源 53 Bitmap bit=BitmapFactory.decodeResource(getResources(), DRAW_IMG_ID[random]); 54 //一个ImageSpan,用于插入的存放待插入的图片 55 ImageSpan imageSpan=new ImageSpan(InImageActivity.this,bit); 56 SpannableString spannableString=new SpannableString("img"); 57 spannableString.setSpan(imageSpan, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 58 edImage.append(spannableString); 59 } 60 }); 61 62 } 63 64 65 66 67 } 显示效果,点击按钮随机添加标签: 既然EditText主要是用来获取用户输入的信息的,那么第二个例子就来讲讲用户输入时候内容的验证吧。在XML Attribute中,有一些属性可以设置输入验证的范围内容,不过此为TextView类的属性,因为TextView无法输入,此处在EditText中讲解说明。 android:digits:指定特定能被输入的字符。 android:inputType:设定输入的类型,下面仅介绍一些常用的,多项可以使用“|”分割。 textUri:必须是一个URL。 textEmailAddress:Email地址 textPassword:密码。 number:数字。 android:numeric:指定数字输入类型,多项可以使用“|”分割。 integer:数字。 decimal:浮点类型。 signed:带符号。 以上属性仅仅是为了限制用户的输入,还有一些输入需要给用户以提示错误信息。这里将使用到setError()方法,如果设定了错误提示信息,会在EditText旁边以感叹号的形式显示。 布局代码: 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <TextView 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:text="使用Android:digits属性(仅输入数字与abcde)" /> 11 12 <EditText 13 android:id="@+id/etNum" 14 android:layout_width="200dp" 15 android:layout_height="wrap_content" 16 android:layout_margin="10dp" 17 android:digits="123456789abcde" 18 /> 19 <TextView 20 android:layout_width="wrap_content" 21 android:layout_height="wrap_content" 22 android:text="使用Android:inputtype属性(仅输入Email)" /> 23 24 <EditText 25 android:layout_width="200dp" 26 android:layout_height="wrap_content" 27 android:layout_margin="10dp" 28 android:inputType="textPassword" 29 /> 30 <TextView 31 android:layout_width="wrap_content" 32 android:layout_height="wrap_content" 33 android:text="使用Android:inputtype属性(仅输入密码)" /> 34 35 <EditText 36 android:layout_width="200dp" 37 android:layout_height="wrap_content" 38 android:layout_margin="10dp" 39 android:numeric="decimal|signed" 40 /> 41 <Button 42 android:id="@+id/btnValidation" 43 android:text="验证第一个输入框是否为123" 44 android:layout_width="wrap_content" 45 android:layout_height="wrap_content"/> 46 </LinearLayout> Java代码: 1 package cn.bgxt.androiduiedittext; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.view.View; 6 import android.widget.Button; 7 import android.widget.EditText; 8 9 public class EditValidationActivity extends Activity { 10 11 private Button btnValidation; 12 private EditText etNum; 13 public EditValidationActivity() { 14 // TODO Auto-generated constructor stub 15 } 16 @Override 17 protected void onCreate(Bundle savedInstanceState) { 18 // TODO Auto-generated method stub 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.editvalidation_activity); 21 btnValidation=(Button)findViewById(R.id.btnValidation); 22 etNum=(EditText)findViewById(R.id.etNum); 23 24 btnValidation.setOnClickListener(new View.OnClickListener() { 25 26 @Override 27 public void onClick(View v) { 28 // TODO Auto-generated method stub 29 String num=etNum.getText().toString().trim(); 30 if(!num.equals("123")) 31 { 32 etNum.setError("请输入123"); 33 } 34 } 35 }); 36 37 38 } 39 } 效果展示: 如果点击验证按钮,而第一个文本框输入的不是123,则提示错误信息: 示例代码下载 总结 以上就讲解了EditText在实际项目中常用的效果,虽然大部分使用的是TextView的属性设置的效果,但是Android下还有一些其他的供用户输入的控件,可以使用,所以才以这样的继承结构实现属性。 本文转自承香墨影博客园博客,原文链接:http://www.cnblogs.com/plokmju/p/Android_UIEditText.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

UI组件-对话框

前言 不要嫌前进的慢,只要一直在前进就好。 AlertDialog组件 AlertDialog的功能很强大,它生成的对话框可分为如下4个区域。 图标区 标题区 内容区 按钮区 从上面这个结构来看创建对话框需要以下几步。 创建AlertDialog.Builder对象 调用AlertDialog.Builder的setTitle()或setCustomTitle()方法设置标题。 调用AlertDialog.Builder的setIcon()方法设置图标。 调用AlertDialog.Builder的相关设置方法设置对话框内容。 调用AlertDialog.Builder的setPositiveButton()、setNegativeButton()或setNeutralButton()方法添加多个按钮。 调用AlertDialog.Builder的create()方法创建AlertDialog对象,再调用AlertDialog对象的show()方法将该对话框显示出来。 其中第4步设置对话框的内容有如下6种方法来指定。 setMessage():设置对话框内容为简单文本。 setItems():设置对话框内容为简单列表项。 setSingleChoiceItems():设置对话框内容为单选列表项。 setMultiChoiceItems():设置对话框内容为多选列表项。 setAdapter():设置对话框内容为自定义列表项。 setView():设置对话框内容为自定义View。 代码示例 alertdialog.xml <?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="match_parent" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/show" android:textSize="20dp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="简单对话框" android:onClick="simple" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="简单列表项对话框" android:onClick="simpleList" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="单选列表项对话框" android:onClick="singleChoice" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="多选列表项对话框" android:onClick="multiChoice" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="自定义列表项对话框" android:onClick="customList" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="自定义View对话框" android:onClick="customView" /> </LinearLayout> MainActivity.java private AlertDialog.Builder setPositiveButton(AlertDialog.Builder builder) { //调用setPositiveButton方法添加“确定”按钮 return builder.setPositiveButton("确定", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub show.setText("单击了【确定】按钮!"); } }); } private AlertDialog.Builder setNegativeButton(AlertDialog.Builder builder) { //调用setPositiveButton方法添加“确定”按钮 return builder.setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub show.setText("单击了【取消】按钮!"); } }); } 提示消息的对话框 public void simple(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(this) .setTitle("简单对话框") //设置标题 .setIcon(R.drawable.ic_launcher) //设置图标 .setMessage("对话框测试内容\n第二行内容"); //AlertDialog.Builder添加确定按钮 setPositiveButton(builder); //AlertDialog.Builder添加取消按钮 setNegativeButton(builder) .create() .show(); } 简单列表项对话框 public void simpleList(View v) { final String items[] = {"西游记","三国演义","水浒传","红楼梦"}; AlertDialog.Builder builder = new AlertDialog.Builder(this) //设置对话框标题 .setTitle("简单列表项对话框") //设置图标 .setIcon(R.drawable.ic_launcher) //设置内容 .setItems(items, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { show.setText("您选中了《" + items[which] + "》"); } }); //为AlertDialog。Builder添加“确定”按钮 setPositiveButton(builder); //为AlertDialog。Builder添加“取消”按钮 setNegativeButton(builder) .create() .show(); } 单选列表项对话框 public void singleChoice(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(this) // 设置对话框标题 .setTitle("单选列表项对话框") // 设置图标 .setIcon(R.drawable.ic_launcher) // 设置单选列表项,默认选中第二项 .setSingleChoiceItems(items, 1, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { show.setText("您选中了《" + items[which] + "》"); } }); // 为AlertDialog。Builder添加“确定”按钮 setPositiveButton(builder); // 为AlertDialog。Builder添加“取消”按钮 setNegativeButton(builder) .create() .show(); } 多选列表项对话框 public void multiChoice(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(this) // 设置对话框标题 .setTitle("多选列表项对话框") // 设置图标 .setIcon(R.drawable.ic_launcher) // 设置多选列表项,默认勾选第三项 .setMultiChoiceItems(items, new boolean[]{false, false, true, false},null); // 为AlertDialog。Builder添加“确定”按钮 setPositiveButton(builder); // 为AlertDialog。Builder添加“取消”按钮 setNegativeButton(builder) .create() .show(); } 自定义列表项对话框 public void customList(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(this) // 设置对话框标题 .setTitle("自定义列表项对话框") // 设置图标 .setIcon(R.drawable.ic_launcher) // 设置自定义列表项 .setAdapter(new ArrayAdapter<String>(this, R.layout.array_item, items), null); // 为AlertDialog。Builder添加“确定”按钮 setPositiveButton(builder); // 为AlertDialog。Builder添加“取消”按钮 setNegativeButton(builder) .create() .show(); } 自定义View对话框 public void customView(View v) { TableLayout loginForm = (TableLayout) getLayoutInflater().inflate(R.layout.login, null); new AlertDialog.Builder(this) .setIcon(R.drawable.ic_launcher) .setTitle("自定义View对话框") .setView(loginForm) .setPositiveButton("登陆", null) .setNegativeButton("取消", null) .create() .show(); } 效果 提示消息的对话框 Screenshot_20171024-093905.png 简单列表项对话框 Screenshot_20171024-094839.png 单选列表项对话框 Screenshot_20171024-095730.png 多选列表项对话框 Screenshot_20171024-100031.png 自定义列表项对话框 Screenshot_20171024-100446.png 自定义View对话框 Screenshot_20171024-101745.png 提示 不仅setAdapter()方法可以接受Adapter作为参数,setSingleChoice方法也可以接受Adapter作为参数,也可以传入Cursor(相当于数据库查询结果集)作为参数。 PopupWindow组件 PopupWindow组件与AlertDialog功能相似,主要的区别就是AlertDialog不能指定显示位置,只能默认显示在屏幕中间。而PopupWindow组件更加灵活,任意位置都可以显示。 使用PoppupWindow创建对话框只要如下两步。 调用PopupWindow的构造器创建PopupWindow对象。 调用PopupWindow的showAsDropDown(View v)方法将PopupWindow作为v组件的下拉组件显示;或调用PopupWindow的showAtLocation()方法将PopupWindow在指定位置显示出来。 代码示例 使用showAtLocation()方法显示 popup_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" > <Button android:id="@+id/bn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="弹出POPUP窗口" /> </LinearLayout> popup.xml <?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="200dp" android:orientation="vertical" > <ImageView android:layout_width="500dp" android:layout_height="wrap_content" android:src="@drawable/kaola" /> <Button android:layout_gravity="center_horizontal" android:id="@+id/close" android:text="关闭" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> MainActivity.java public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.popup_main); //加载R.layout.popup对应的界面布局文件 View root = LayoutInflater.from(MainActivity.this).inflate(R.layout.popup, null); //创建PopupWindow对象 final PopupWindow popup = new PopupWindow(root,LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT,true); Button button = (Button) findViewById(R.id.bn); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { View rootView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popup_main, null); //将PopupWindow显示在指定位置 popup.showAtLocation(rootView, Gravity.BOTTOM, 0, 0); } }); //获取PopupWindow中的“关闭”按钮 root.findViewById(R.id.close).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //关闭PopupWindow popup.dismiss(); } }); } } 使用showAsDropDown()方法显示 main.xml <?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="match_parent" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:textColor="#50484b" android:padding="10dp" android:text="返回" /> <TextView android:id="@+id/menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:textColor="#50484b" android:padding="10dp" android:text="菜单" /> </RelativeLayout> </LinearLayout> popup_layout.xml <?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:orientation="vertical" android:paddingBottom="2dp" > <View android:layout_width="match_parent" android:layout_height="2.25dp" android:background="#fa7829" /> <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="halo" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#f00" /> <TextView android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="halo1" /> </LinearLayout> MainActivity.java public class MainActivity extends Activity { private PopupWindow popup; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView) findViewById(R.id.menu); tv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showPopupWindow(); } }); } private void showPopupWindow() { View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popup_layout, null); popup = new PopupWindow(contentView); popup.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); popup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); TextView tv1 = (TextView) contentView.findViewById(R.id.tv1); TextView tv2 = (TextView) contentView.findViewById(R.id.tv2); tv1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "tv1", Toast.LENGTH_SHORT).show(); popup.dismiss(); } }); tv2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "tv2", Toast.LENGTH_SHORT).show(); popup.dismiss(); } }); popup.showAsDropDown(tv); } } 效果 使用showAtLocation()方法显示 Screenshot_20171024-132525.png 使用showAsDropDown()方法显示 Screenshot_20171024-135937.png 提示 PopupWindow最基本的三个条件是一定要设置contentView,width,height,不然PopupWindow不显示。 DatePickerDialog和TimerPickerDialog组件 这两个组件的功能和用法非常简单,只要如下两步即可。 通过new关键字创建DatePickerDialog、TimerPickerDialog实例,调用它们的show()方法即可将日期选择对话框、时间选择对话框显示出来。 为DatePickerDialog、TimePickerDialog绑定监听器,这样可以保证用户设置事件时触发监听器。 代码示例 pickerdialog.xml <?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="match_parent" android:orientation="vertical" > <EditText android:id="@+id/show" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="bt_datepicker" android:text="日期选择对话框" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="bt_timepicker" android:text="时间选择对话框" /> </LinearLayout> MainActivity.java public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.pickerdialog); } public void bt_timepicker(View v) { Calendar c = Calendar.getInstance(); //创建一个DatePickerDialog对话框实例 new DatePickerDialog(MainActivity.this, new OnDateSetListener() { @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { EditText show = (EditText) findViewById(R.id.show); show.setText("您选择了:" + year + "年" + (monthOfYear + 1) + "月" + dayOfMonth + "日"); } }, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH)).show(); } public void bt_datepicker(View v) { Calendar c = Calendar.getInstance(); new TimePickerDialog(MainActivity.this, new OnTimeSetListener() { @Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) { EditText show = (EditText) findViewById(R.id.show); show.setText("您选择了:" + hourOfDay + "时" + minute + "分"); } } ,c.get(Calendar.HOUR_OF_DAY) ,c.get(Calendar.MINUTE) , true).show();//true表示24小时制 } } 效果 Screenshot_20171024-142038.png Screenshot_20171024-142044.png ProgressDialog组件 ProgressDialog代表了进度对话框。使用ProgressDialog创建进度对话框有如下两种方式。 如果只是创建简单的进度对话框,那么调用ProgressDialog提供的静态show()方法显示对话框即可。 创建ProgressDialog,然后调用方法对对话框里的进度条进行设置,设置完成后将对话框显示出来即可。 对进度对话框进行设置的方法如下。 setIndeterminate(boolean indeterminate):设置对话框里的进度条不显示进度值。 setMax(int max):设置对话框里进度条的最大值。 setMessage(CharSequence message):设置对话框里的提示消息。 setProgress(int value);设置对话框里进度条的进度值。 setProgressStyle(int style):设置对话框里进度条的风格。 代码示例 progressdialog.xml <?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="match_parent" android:orientation="vertical" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="show_Progress1" android:text="环形进度条" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="show_Progress2" android:text="不显示进度的进度条" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="show_Progress3" android:text="显示进度的进度条" /> </LinearLayout> MainActivity.java public class MainActivity extends Activity { final static int MAX_PROGRESS = 100; //该程序模拟填充长度为100的数组 private int[] data = new int[50]; //记录进度对话框的完成百分比 int progressStatus = 0; int hasData = 0; ProgressDialog pd1,pd2; //定义一个负责更新进度的Handler Handler handler = new Handler() { @Override public void handleMessage(Message msg) { //表明该消息是由该程序发送的 if(msg.what == 1) { pd2.setProgress(progressStatus); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.progressdialog); } public void show_Progress1(View v) { //调用静态方法显示环形进度条 ProgressDialog.show(this, "任务执行中", "任务执行中,请等待",false,true); } public void show_Progress2(View v) { pd1 = new ProgressDialog(MainActivity.this); //设置对话框标题 pd1.setTitle("任务执行中"); //设置对话框显示的内容 pd1.setMessage("任务正在执行中,请等待。。。"); //设置对话框能用"取消"按钮关闭 pd1.setCancelable(true); //设置对话框的进度条风格 pd1.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //设置对话框的进度条是否显示进度 pd1.setIndeterminate(false); pd1.show(); } public void show_Progress3(View v) { //将进度条的完成进度重设为0 progressStatus = 0; //重新开始填充数组 hasData = 0; pd2 = new ProgressDialog(MainActivity.this); //设置对话框的标题 pd2.setTitle("任务完成百分比"); //设置对话框的显示内容 pd2.setMessage("耗时任务的完成百分比"); //设置对话框不能用"取消"按钮关闭 pd2.setCancelable(false); //设置对话框的进度条风格 pd2.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //设置对话框的进度条是否显示进度条 pd2.setIndeterminate(false); pd2.show(); new Thread() { public void run() { while(progressStatus < MAX_PROGRESS) { //获取耗时操作的完成百分比 progressStatus = MAX_PROGRESS * doWork() / data.length; //发送空消息到Handler handler.sendEmptyMessage(1); } //如果任务已完成 if(progressStatus >= MAX_PROGRESS) { //关闭对话框 pd2.dismiss(); } } }.start(); } public int doWork() { //为数组元素赋值 data[hasData++] = (int)(Math.random() * 100); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return hasData; } } 效果 progress1.PNG Screenshot_20171024-145850.png Screenshot_20171024-145327.png

优秀的个人博客,低调大师

UI组件-ViewAnimator及其子类

前言 凡事不必太在意,一切随缘随心,缘深多聚聚,缘浅随它去。 ViewSwitcher的功能与用法 ViewSwitcher代表了视图切换组件,它本身继承了FrameLayout,因此可以将多个View层叠在一起,每次只显示一个组件。当程序控制从一个View切换到另一个View时,ViewSwitcher支持指定的动画。下面来看看仿Android系统Launcher界面示例。假设一共有100个应用程序,每个页面显示20个,每行4个。 代码示例 activity_main.xml <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" > <!-- 定义个一个ViewSwitcher组件 --> <ViewSwitcher android:id="@+id/viewSwitcher" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- 定义滚动到上一屏的按钮 --> <Button android:id="@+id/button_prev" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:onClick="prev" android:text="<" /> <!-- 定义滚动到下一屏的按钮 --> <Button android:id="@+id/button_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:onClick="next" android:text=">" /> </RelativeLayout> labelicon.xml <?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="match_parent" android:orientation="vertical" android:gravity="center"> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" /> </LinearLayout> slidelistview.xml <?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:numColumns="4" android:gravity="center" /> slide_in_left.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 设置从右边拖进来的动画,android:duration指定动画持续时间 --> <translate android:fromXDelta="0" android:toXDelta="100%p" android:duration="@android:integer/config_mediumAnimTime" /> </set> slide_out_right.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 设置从左边拖出去的动画,android:duration指定动画持续时间 --> <translate android:fromXDelta="-100%p" android:toXDelta="0" android:duration="@android:integer/config_mediumAnimTime" /> </set> slide_in_right.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 设置从右边拖进来的动画,android:duration指定动画持续时间 --> <translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="@android:integer/config_mediumAnimTime" /> </set> slide_out_left.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 设置从左边拖出去的动画,android:duration指定动画持续时间 --> <translate android:fromXDelta="0" android:toXDelta="-100%p" android:duration="@android:integer/config_mediumAnimTime" /> </set> MainActivity.java public class MainActivity extends Activity { //定义一个常量,用于显示每屏显示的应用程序数 public static final int NUMER_PER_SCREEN = 20; //代表应用程序的内部类 public static class DataItem { //应用程序名称 public String dataName; //应用程序图片 public Drawable drawable; } //保存系统所有应用程序的List集合 private ArrayList<DataItem> items = new ArrayList<DataItem>(); //记录当前正在显示第几屏的程序 private int screenNo = -1; //保存程序所占的总屏数 private int screenCount; ViewSwitcher switcher; //创建LayoutInflater对象 LayoutInflater inflater; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); inflater = LayoutInflater.from(MainActivity.this); //创建一个包含100个元素的list集合,用于模拟包含100个应用程序 for (int i = 0; i < 100; i++) { String label = "" + i; Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher); DataItem item = new DataItem(); item.dataName = label; item.drawable = drawable; items.add(item); } //计算应用程序所占的总屏数 //如果应用程序的数量能整除NUMBER_PER_SCREEN,除法的结果就是总屏数 //如果不能整除,总屏数应该是除法的结果加1 screenCount = items.size() % NUMER_PER_SCREEN == 0 ? items.size() / NUMER_PER_SCREEN : items.size() / NUMER_PER_SCREEN + 1; switcher = (ViewSwitcher) findViewById(R.id.viewSwitcher); switcher.setFactory(new ViewFactory() { //实际上是返回一个GridView组件 @Override public View makeView() { //加载R.Layout。slidelistview组件,实际上就是一个GridView return inflater.inflate(R.layout.slidelistview, null); } }); next(null); } public void next(View v) { if(screenNo < screenCount - 1) { screenNo++; //为ViewSwitcher的组件显示过程设置动画 switcher.setInAnimation(this,R.anim.slide_in_right); //为ViewSwitcher的组件隐藏过程设置动画 switcher.setInAnimation(this,R.anim.slide_out_left); //控制下一屏将要显示的GridView对应的Adapter ((GridView)switcher.getNextView()).setAdapter(adapter); //单击右边按钮,显示下一屏 switcher.showNext(); } } public void prev(View v) { if(screenNo > 0) { screenNo--; //为ViewSwitcher的组件显示过程设置动画 switcher.setInAnimation(this,R.anim.slide_in_left); //为ViewSwitcher的组件隐藏过程设置动画 switcher.setInAnimation(this,R.anim.slide_out_right); //控制下一屏将要显示的GridView对应的Adapter ((GridView)switcher.getNextView()).setAdapter(adapter); //单击右边按钮,显示下一屏 switcher.showPrevious(); } } //该BaseAdapter负责为每屏显示的GridView提供列表项 private BaseAdapter adapter = new BaseAdapter() { @Override public View getView(int position, View convertView, ViewGroup parent) { View view =convertView; if(convertView == null) { //加载R.layout.labelicon布局文件 view = inflater.inflate(R.layout.labelicon, null); } //获取R.layout.labelicon布局文件中的ImageView组件,并为之设置图标 ImageView imageView = (ImageView) view.findViewById(R.id.imageView); imageView.setImageDrawable(getItem(position).drawable); //获取R.layout.labelicon布局文件中的TextView组件,并为之设置文本 TextView textView = (TextView) view.findViewById(R.id.textView); textView.setText(getItem(position).dataName); return view; } @Override public long getItemId(int position) { return position; } @Override public DataItem getItem(int position) { //根据screenNo计算第position个列表项的数据 return items.get(screenNo * NUMER_PER_SCREEN + position); } @Override public int getCount() { //如果已经到了最后一屏,且应用程序的数量不能整除NUMBER_PER_SCREEN if(screenNo == screenCount - 1 && items.size() % NUMER_PER_SCREEN != 0) { //最后一屏显示的程序数为应用程序的数量对NUMBER_PER_SCREEN求余 return items.size() % NUMER_PER_SCREEN; } //否则每屏显示的程序数量为NUMER_PER_SCREEN return NUMER_PER_SCREEN; } }; } 效果 Screenshot_20171020-151447.png 提示 也许你会对这个程序的一些代码感到疑惑,比如说这段代码。 View view =convertView; if(convertView == null) { //加载R.layout.labelicon布局文件 view = inflater.inflate(R.layout.labelicon, null); } 其实它只不过是ListView缓存的一种手段,这样在你快速滑动的时候可以防止内存溢出。 点击按钮会切换到另一个页面,这可不是跳转到另一Activity。以后我会写关于手势操作的文章,这样就可以通过手势来进行页面切换。 ImageSwitcher ImageSwitcher继承了ViewSwitcher,因此它具有与ViewSwitcher相同的特征:可以在切换View组件时使用动画效果。ImageSwitcher的操作很简单,只需要如下两步即可。 为ImageSwitcher提供一个ViewFactory,该ViewFactory生成的View组件必须是ImageView。 需要切换图片时,只要调用ImageSwitcher的setImageDrawable(Drawable drawable)、setImageResource(int resid)和setImageURI(Uri uri)方法更换图片即可。 代码示例 imageswitch.xml <?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="match_parent" android:orientation="vertical" android:gravity="center_horizontal" > <!-- 定义一个GridView组件 --> <GridView android:id="@+id/grid01" android:layout_width="match_parent" android:layout_height="wrap_content" android:horizontalSpacing="2dp" android:verticalSpacing="2dp" android:numColumns="4" android:gravity="center" /> <!-- 定义一个ImageSwitcher --> <ImageSwitcher android:id="@+id/switcher" android:layout_width="300dp" android:layout_height="300dp" android:layout_gravity="center_horizontal" android:inAnimation="@android:anim/fade_in" android:outAnimation="@android:anim/fade_out" /> </LinearLayout> MainActivity.java public class MainActivity extends Activity { int []imageIds = new int[] { R.drawable.baxianhua,R.drawable.dengta,R.drawable.ic_launcher,R.drawable.juhua, R.drawable.kaola,R.drawable.qie,R.drawable.shamo,R.drawable.shuimo, R.drawable.yujinx,R.drawable.baxianhua,R.drawable.dengta,R.drawable.ic_launcher, R.drawable.juhua,R.drawable.kaola,R.drawable.qie,R.drawable.shamo }; ImageSwitcher switcher; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.imageswitch); List<Map<String,Object>> listItems = new ArrayList<Map<String,Object>>(); for (int i = 0; i < imageIds.length; i++) { Map<String,Object> listItem = new HashMap<String, Object>(); listItem.put("image", imageIds[i]); listItems.add(listItem); } //获取显示图片的ImageSwitcher switcher = (ImageSwitcher) findViewById(R.id.switcher); //为ImageSwitcher设置图片切换的动画效果 switcher.setFactory(new ViewFactory() { @Override public View makeView() { //创建ImageView对象 ImageView imageView = new ImageView(MainActivity.this); imageView.setScaleType(ScaleType.FIT_CENTER); imageView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); return imageView; } }); SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems, R.layout.cell, new String[] {"image"}, new int[] {R.id.image1}); GridView grid = (GridView) findViewById(R.id.grid01); grid.setAdapter(simpleAdapter); //添加列表项被选中的监听器 grid.setOnItemSelectedListener(new GridView.OnItemSelectedListener() { @Override public void onNothingSelected(AdapterView<?> parent) { } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { //显示被选中的图片 switcher.setImageResource(imageIds[position]); } }); grid.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //显示被选中的图片 switcher.setImageResource(imageIds[position]); } }); } } 效果 Screenshot_20171020-161723.png 提示 TextSwitcher组件 TextSwitcher组件继承了ViewSwitcher组件,与上面的ImageSwitcher组件的用法相似,唯一不同的是TextSwitcher所需的ViewFactory的makeView()方法必须返回一个TextView组件。 代码示例 textswitcher.xml <?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="match_parent" > <!-- 定义一个TextSwitcher,并指定了文本切换时的动画效果 --> <TextSwitcher android:id="@+id/textSwitcher" android:layout_width="match_parent" android:layout_height="wrap_content" android:inAnimation="@android:anim/slide_in_left" android:outAnimation="@android:anim/slide_out_right" android:onClick="next" /> </LinearLayout> MainActivity.java public class MainActivity extends Activity { TextSwitcher textSwitcher; String[] strs = new String[] { "水浒传","三国演义","红楼梦","西游记" }; int curStr; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.textswitcher); textSwitcher = (TextSwitcher) findViewById(R.id.textSwitcher); textSwitcher.setFactory(new ViewFactory() { @Override public View makeView() { TextView tv = new TextView(MainActivity.this); tv.setTextSize(40); tv.setTextColor(Color.MAGENTA); return tv; } }); //调用next方法显示一个字符串 next(null); } public void next(View v) { textSwitcher.setText(strs[curStr++ % strs.length]); } } 效果 Screenshot_20171023-092903.png 点击文本会出现切换效果 提示 TextSwitcher与TextView的功能有点相似,它们都可用于显示文本内容,区别在于TextSwitcher的效果更炫,它可以指定文本切换时的动画效果。 ViewFlipper组件 ViewFlipper组件继承了ViewAnimator,它可以调用addView(View v)方法添加多个组件,一旦向ViewFlipper中添加多个组件之后,ViewFlipper就可使动画控制多个组件之间的切换效果。它与前边介绍的AdapterViewFlipper有较大的相似性,区别就是ViewFlipper需要开发者通过addView(View v)添加多个View,而AdapterViewFlipper只要传入一个Adapter,Adapter将会负责提供多个View。 代码示例 viewflipper.xml <?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" > <ViewFlipper android:id="@+id/details" android:layout_width="match_parent" android:layout_height="match_parent" android:flipInterval="1000" > <ImageView android:src="@drawable/baxianhua" android:layout_width="match_parent" android:layout_height="wrap_content" /> <ImageView android:src="@drawable/dengta" android:layout_width="match_parent" android:layout_height="wrap_content" /> <ImageView android:src="@drawable/juhua" android:layout_width="match_parent" android:layout_height="wrap_content" /> </ViewFlipper> <Button android:text="<" android:onClick="prev" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" /> <Button android:text="自动播放" android:onClick="auto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerInParent="true" /> <Button android:text=">" android:onClick="next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" /> </RelativeLayout> MainAcitivity.java public class MainActivity extends Activity { private ViewFlipper viewFlipper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.viewflipper); viewFlipper = (ViewFlipper) findViewById(R.id.details); } public void prev(View v) { viewFlipper.setInAnimation(this, R.anim.slide_in_right); viewFlipper.setOutAnimation(this, R.anim.slide_out_left); // 显示上一个组件 viewFlipper.showPrevious(); // 停止自动播放 viewFlipper.stopFlipping(); } public void next(View v) { viewFlipper.setInAnimation(this, R.anim.slide_in_left); viewFlipper.setOutAnimation(this, R.anim.slide_out_right); // 显示下一个组件 viewFlipper.showNext(); // 停止自动播放 viewFlipper.stopFlipping(); } public void auto(View v) { viewFlipper.setInAnimation(this, R.anim.slide_in_left); viewFlipper.setOutAnimation(this, R.anim.slide_out_right); //开始自动播放 viewFlipper.startFlipping(); } } 效果 Screenshot_20171023-100803.png 提示 ViewFlipper可以指定与AdapterViewFlipper相同的XML属性。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册