最近做一个页面,仿制以下两个图,一个是横屏,一个竖屏。这是一款名字叫IMDb的手机软件,其中最上面中间是一个图;然后下来是三个tab样式的(Movies、TV、People)三个可以切换,切换是三个不同页面;下面是一个横排的图片,图片可以左右滑动显示;下面是一个list列表,此列表每一行最左边是一个图片,中间是文字,最右边是一个小箭头图标。
首先解决的是最上面图片居中显示,在LinearLayout标签中加入android:gravity="center_horizontal",这个表示横向居中显示。这样的话切换横竖屏之后,图片也是在中间的。
再次,解决三个(Movies、TV、People)三个可以切换的页面。开始想到用tab标签来实现,后来发现tab只能用在头部而且最上面不能有图片。所以尝试了大概1-2个小时后,放弃使用tab,改用LinearLayout来控制,每点不同的LinearLayout时,页面显示不同,
具体代码如下:在main.xml中,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:gravity="top">
<include layout="@layout/foot" />
</LinearLayout>
这里用到了include标签,是引用另外一个页面的意思,类似与html中的include ,效果类似,将foot.xml文件中的页面显示在此LinearLayout中,
foot.xml文件如下:最外是一个横排的LinearLayout ,里面包裹三个LinearLayout,背景设置为灰色。代码如下,其中一个
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/Movies"
android:background="@drawable/tab_one_normal" android:gravity="center_horizontal">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Movies"
android:gravity="center" android:paddingTop="5px"
android:textColor="#FFFFFF" android:textSize="20px"
android:textStyle="bold"/>
</LinearLayout>
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:src="@drawable/line" />
在Java类中:默认movies为选中的LinearLayout,对每个LinearLayout进行监听,点击之后背景变化,原来被点中的LinearLayout则变为灰色,点中的变为黑色。
private LinearLayout movies, tv, people;
movies = (LinearLayout) findViewById(R.id.Movies);
tv = (LinearLayout) findViewById(R.id.TV);
people = (LinearLayout) findViewById(R.id.People);movies.setBackgroundResource(R.drawable.tab_two_highlight);//默认为选中的LinearLayout
movies.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
movies.setBackgroundResource(R.drawable.tab_two_highlight);
tv.setBackgroundResource(R.drawable.tab_one_normal);
people.setBackgroundResourc(R.drawable.tab_one_normal);
}
});
这样就完成了最上边的两部分,效果如下图:
接下来,该横向显示图片;这里使用了android apidemo中的一个例子,大家也可以参考,在view-》Gallery1中。
这里使用到了Gallery标签,具体实现如下:
在main.xml中使用<include layout="@layout/imagegallery" />
imagegallery.xml文件中:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:background="#FFFFFF"
android:layout_marginBottom="10px">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:background="#FFFFFF"
android:paddingTop="10px" android:paddingLeft="7px">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="这是一个画廊"
android:textColor="#000000" android:paddingLeft="5px"
android:id="@+id/iamge_text" />
</LinearLayout>
<Gallery android:id="@+id/myGallery" android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
在value文件夹下新建attrs.xml(这里apidemo中就是这么使用的,所以照葫芦画瓢呗),文件内容如下:
<resources>
<!– These are the attributes that we want to retrieve from the theme
in view/Gallery1.java –>
<declare-styleable name="Gallery1">
<attr name="android:galleryItemBackground" />
</declare-styleable>
<declare-styleable name="LabelView">
<attr name="text" format="string" />
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>
然后在ImageAdapter.java文件中:
继承BaseAdapter,编写它的四个方法,getCount得到图片的个数,getItem和getItemId,得到图片的id,getView(int position, View convertView, ViewGroup parent)得到视图。
构造方法public ImageAdapter(Context context),
具体代码如下:
public class ImageAdapter extends BaseAdapter{
int mGalleryItemBackground;
private Context mContext;
private Integer[] mImageIds = {
R.drawable.gallery_photo_1,
R.drawable.gallery_photo_2,
R.drawable.gallery_photo_3,
R.drawable.gallery_photo_4,
R.drawable.gallery_photo_5,
R.drawable.gallery_photo_6,
R.drawable.gallery_photo_7,
R.drawable.gallery_photo_8
};
public ImageAdapter(Context context){
mContext = context;
TypedArray typedArray = context.obtainStyledAttributes(R.styleable.Gallery1);
mGalleryItemBackground = typedArray.getResourceId(
R.styleable.Gallery1_android_galleryItemBackground, 0);
typedArray.recycle();
}
@Override
public int getCount() {
return mImageIds.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
imageView.setImageResource(mImageIds[position]);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setLayoutParams(new Gallery.LayoutParams(138,100));
imageView.setPadding(0, 1, 15, 0);
imageView.setBackgroundResource(mGalleryItemBackground);
return imageView;
}
}
在IMDbDemo主类中加入:
private Gallery gallery;
oncreate方法中加入:
gallery = (Gallery)findViewById(R.id.myGallery);
gallery.setAdapter(new ImageAdapter(movies.getContext()));
gallery.setSelection(1);//图片第二个被选中
默认是movies点中时,显示movies下的横排图片,
另外建立两个类,类似ImageAdapter,只需将Integer[] mImageIds下的图片id 改变即可,然后在点击的时候,使用下面两个方法,将ImageAdapter改成具体的类名字,将movies.getContext()改成具体的tv或者是people的context即可。
gallery.setAdapter(new ImageAdapter(movies.getContext()));
gallery.setSelection(1);//图片第二个被选中
尝试一下,是否效果如原版?这里有些滥竽充数的概念,首先,原版中图片是顶在左侧的,而我使用setSelection方法,让它首次定义在第二个图片上,这里的图片宽度是计算好了的,竖屏宽是320px,Gallery.LayoutParams(138,100));属性是设置了一下选中的那个图片的宽度和高度,所以,看起来显示效果跟原版是一样的,其实是赖于充数。如果切换成横屏的话,则应该默认应该定义在第二个图片上,这样就跟原版的保持一致了。
效果图如下:
最后是最下面的list了,这里主要说一下横竖屏切换的问题。原版中那三个(Movies、TV、People)横竖屏切换后长度随之变化,而且下面的list,不能说是list,应该说是类似list的视图中,每一行最右边的小箭头都是靠右的,但是我这里每规定一个list的时候都是固定左边的图标,中间的文字,右边的箭头这三个所占用的宽度,都是规定死的,所以横竖屏切换的时候,需要设置中间文字部分的LinearLayout 的宽度了。
首先得到是否是宽屏,
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
screenWidth = display.getWidth();
screenHeight = display.getHeight();
if(screenWidth>screenHeight)表示竖屏
使用下面的方法,设置LinearLayout的宽,高;第一个参数是宽,第二个参数是高。
movies.setLayoutParams(new LinearLayout.LayoutParams(189,40));
tv.setLayoutParams(new LinearLayout.LayoutParams(189,40));
people.setLayoutParams(new LinearLayout.LayoutParams(189,40));
这里要提一点,getWindowManager();我一直没有搞明白到底是什么.getWindowManager();所以在我的list中,无法得到屏幕的宽和高,这里,王老师教了一招,就是创建ListAdapter的时候直接告诉这个ListAdapter是横屏还是竖屏,所以在ListAdapter类中,构造方法中,加入了一个布尔类型的参数,具体代码如下:
public ListAdapter(Context context, int textViewResourceId,
List<String> list,Boolean bl) {
super(context, textViewResourceId,list);
item = list;
screen = bl;
}
然后再设置文字所在的LinearLayout的宽度和高度。这样就解决了横竖屏的所有的问题,效果图如下:
最后遗留一个问题:
就是官方文档中有说在ScollView中不要添加ListView,否则ListView是显示不正常的,试验过,确实如官方文档所说,起码2.1之前的都是这样效果,ListView只显示一个List那样的高度。而原版中可以看到除了最上边的无法滑动外,整个下边的包括横排的图,整个都可以上下滑动的,这样有利于在切换成横屏的时候下面不至于太少的空间而看不全。我只有一种解释这样的效果,就是写死了下面的内容,不使用ListView。因为我看了网上解决这个bug的方法在我这里都没见到效果。我也比较赞成网上最欠抽的方法,最好两个不缠在一块儿使用。
源代码见:http://henzil.googlecode.com/svn/trunk/android.IMDbDemo/
You can leave a response, or trackback from your own site.
楼主:
你对TabHost的理解有所偏颇,TabHost并没有只是TabActivity这么简单,完全可以自己去实现TabWidget的样式和位置,可以参考Contacts里面的tab,有些就是放在下面的。