您的位置:首页 > 移动开发 > Android开发

ViewSwitcher实现程序列表分屏和动画效果

2011-06-05 17:57 736 查看
http://winuxxan.blog.51cto.com/2779763/533289

 

 

 Android的Launcher界面功能菜单是一个列表,当应用程序较多时,可以向下滑动查看其它,如下图。那能不能将功能菜单做成横向拖动,并且分屏的效果呢?





    本文对该问题进行研究,要达到的目标如下:
    1、可以实现应用程序的分屏显示,当一屏放不下时,放入另一个屏。
    2、屏与屏之间切换为横向。
    3、屏与屏之间切换时有动画效果,一个屏退出,一个屏出现。
    本文的方法暂时没有解决屏幕切换随着手的移动而逐渐切换的问题,但是本文的屏幕切换可以采用手势的方式。
    分屏和横向显示不是很难解决的问题,关键问题在于动画效果的实现。由于在屏幕切换时两个屏同时发生动画,一个退出,一个进入,因此至少要同时存在两个View。实际上Android已经为我们考虑了这种情况。ViewSwitcher就是专门针对这种情况而设计的。
    ViewSwitcher内部保存了两个View,通过我们的控制可以显示前一个和后一个,并且我们可以设置在切换中两个View的动画。View的生成为ViewFactory生成。该类还是比较简单的,需要详细研究参考google文档和源代码。
多的不说,上代码吧。
    首先我们模拟一下功能菜单的数据部分,也就是分几个屏,每个屏有哪些应用之类的东西。注释较多,不多解释。

/** 
* 该类模拟了功能菜单的数据部分 
*/ 
public class MenuData { 
    /**该常量代表每一屏能够容纳的应用程序数目*/ 
    public static final int NUMBER_IN_ONE_SCREEN = 9; 
     
    /**该类代表每个应用程序的数据部分*/ 
    public static class DataItem { 
        public String dataName;   //应用程序名称 
        public Drawable drawable;  //应用程序图标 
    } 
     
    /**该类代表了一个屏的所有应用程序*/ 
    public static class MenuDataOneScreen {  
        ArrayList<DataItem> mDataItems = new ArrayList<DataItem>(); 
    } 
     
    /**该数据时该类的主要部分,所有屏的列表,实际上该类就是代表了所有的屏*/ 
    ArrayList<MenuDataOneScreen> mScreens = new ArrayList<MenuDataOneScreen>(); 
     
    /**对该类进行赋予数据*/ 
    public void setMenuItems(ArrayList<DataItem> dataItems) { 
        int screenNum = dataItems.size() / NUMBER_IN_ONE_SCREEN; 
        int remain = dataItems.size() % NUMBER_IN_ONE_SCREEN; 
        screenNum += remain == 0 ? 0 : 1; 
         
        int pos = 0; 
        for (int i = 0; i < screenNum; i++) { 
            MenuDataOneScreen screen = new MenuDataOneScreen(); 
            for (int j = 0; j < NUMBER_IN_ONE_SCREEN; j++) { 
                if (pos <= dataItems.size() - 1) { 
                    screen.mDataItems.add(dataItems.get(pos)); 
                    pos++; 
                } 
            } 
            mScreens.add(screen); 
        } 
    } 
     
    /**获取屏的数目*/ 
    public int getScreenNumber() { 
        return mScreens.size(); 
    } 
     
    /**根据屏的索引,获取某个屏的数据*/ 
    public MenuDataOneScreen getScreen(int screenIndex) { 
        return mScreens.get(screenIndex); 
    } 


    然后,我们重载ViewFactory类,定义我们如何生成View,生成什么样的View。

public class SlideViewFactory implements ViewFactory{ 
    LayoutInflater mInflater; 
    public SlideViewFactory(Context context) { 
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    } 
     
    /**这个函数就是得到我们要生成的View,这里实际上直接从布局得到, 
    *我们定义的是一个GridView ,一个GridView用于显示一屏的应用程序*/  
    public View makeView() { 
        return mInflater.inflate(R.layout.slidelistview, null); 
    } 


    从上面的代码我们可以看出,我们生成的View实际是一个GridView,GridView要想和数据关联,则需要一个Adapter,因此我们下面定义该Adapter:

public class OneScreenListAdapter extends BaseAdapter{ 
    private MenuDataOneScreen mScreen; 
    private LayoutInflater mInflater; 
     
    public OneScreenListAdapter(Context context) { 
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    } 
     
    /**这里将数据赋予Adapter*/ 
    public void setScreenData(MenuDataOneScreen screenData) { 
        mScreen = screenData; 
    } 
 
    public int getCount() { 
        return mScreen.mDataItems.size(); 
    } 
 
    public Object getItem(int position) { 
        return mScreen.mDataItems.get(position); 
    } 
 
    public long getItemId(int position) { 
        return position; 
    } 
 
    /**该函数中将数据和View进行关联*/ 
    public View getView(int position, View convertView, ViewGroup parent) { 
        View view = convertView; 
        if (convertView == null) { 
            view = mInflater.inflate(R.layout.labelicon, null); 
        }  
     
        ImageView imageView = (ImageView) view.findViewById(R.id.imageview); 
        TextView textView = (TextView) view.findViewById(R.id.textview); 
        imageView.setImageDrawable(mScreen.mDataItems.get(position).drawable); 
        textView.setText(mScreen.mDataItems.get(position).dataName); 
         
        return view; 
    } 
 


    下面是继承ViewSwitcher的部分,用来实现两个屏的切换。

 

/**该部分是ViewSwitcher的重载,用该类实现两个屏的切换和切换的动画实现*/ 
public class SlideMenuSwitcher extends ViewSwitcher{ 
    private MenuData mMenuData; 
    private int mCurrentScreen; 
    private Context mContext; 
     
    public SlideMenuSwitcher(Context context, AttributeSet attrs) { 
        super(context, attrs); 
        setFactory(new SlideViewFactory(context)); 
//      setAnimateFirstView(false); 
        mContext = context; 
    } 
     
    /**通过该方法将数据赋值进去,并且将初始的屏显示出来*/ 
    public void setData(ArrayList<DataItem> dataItems) { 
        mMenuData = new MenuData(); 
        mMenuData.setMenuItems(dataItems); 
        mCurrentScreen = mMenuData.getScreenNumber() / 2; 
         
        GridView listView = (GridView) getCurrentView(); 
        OneScreenListAdapter adapter = new OneScreenListAdapter(mContext); 
        adapter.setScreenData(mMenuData.getScreen(mCurrentScreen)); 
        listView.setAdapter(adapter); 
    } 
     
    /**该方法用于显示下一屏*/ 
    public void showNextScreen() { 
        if (mCurrentScreen < mMenuData.getScreenNumber() - 1) { 
            mCurrentScreen++; 
            setInAnimation(mContext, R.anim.slide_in_right); 
            setOutAnimation(mContext, R.anim.slide_out_left); 
        } else { 
            return; 
        } 
         
        setViewData(mCurrentScreen); 
        showNext(); 
    } 
     
    /**该方法用于显示上一屏*/ 
    public void showPreviousScreen() { 
        if (mCurrentScreen > 0) { 
            mCurrentScreen--; 
            setInAnimation(mContext, R.anim.slide_in_left); 
            setOutAnimation(mContext, R.anim.slide_out_right); 
        } else { 
            return; 
        } 
         
        setViewData(mCurrentScreen); 
        showPrevious(); 
    } 
     
    private void setViewData(int index) { 
        GridView listView = (GridView) getNextView(); 
        OneScreenListAdapter adapter = new OneScreenListAdapter(mContext); 
        adapter.setScreenData(mMenuData.getScreen(index)); 
        listView.setAdapter(adapter); 
    } 

 

    我们将在一个Activity中,将我们做好的东西实现。首先在布局中将我们写的SlideMenuSwitcher。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
    <com.winuxxan.SlideMenu.SlideMenuSwitcher 
        android:id="@+id/slide_view" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_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: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:text="-->" 
    /> 
</RelativeLayout> 

    最后,实现我们的Activity:

public class SlideMenuActivity extends Activity { 
    /** Called when the activity is first created. */ 
    SlideMenuSwitcher switcher; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        switcher = (SlideMenuSwitcher) findViewById(R.id.slide_view); 
        switcher.setData(makeItems());    //将24个应用程序赋值到swithcer中。 
         
        findViewById(R.id.button_next).setOnClickListener(new OnClickListener() { 
             
            public void onClick(View v) { 
                switcher.showNextScreen();  //点击右边按钮,显示下一屏,当然可以采用手势 
            } 
        }); 
         
        findViewById(R.id.button_prev).setOnClickListener(new OnClickListener() { 
             
            public void onClick(View v) { 
                switcher.showPreviousScreen();  //点击左边按钮,显示上一屏,当然可以采用手势 
 
            } 
        }); 
    } 
     
    /**模拟24个应用程序*/ 
    private ArrayList<DataItem> makeItems() { 
        ArrayList<DataItem> items = new ArrayList<DataItem>(); 
        for (int i = 0; i < 24; i++) { 
            String label = "" + i; 
            Drawable drawable = getResources().getDrawable(R.drawable.icon); 
            DataItem item = new DataItem(); 
            item.dataName = label; 
            item.drawable = drawable; 
            items.add(item); 
        } 
         
        return items; 
    } 


    好了,运行我们的应用程序,看下,效果是否是我们想要的?(动画效果没法抓图)



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