仿牛客UI Android版


这是我的第一篇博客,想想还有点小。鸡。动。。。
这篇博客是写给初学者的,也是给自己留个记录以备日后查看。大神们就路过吧!不喜勿喷,有不正的地方还望不吝赐教!事先声明只实现该app的部分功能和UI。


特别声明一下

【标题栏(ActionBar)部分牛客的标题可以向上滑动隐藏,可以使用安卓的suppost-V7实现,为节省时间直接在布局中写出来了,下拉刷新功能也没有实现,app所涉及到的数据均存放在安卓sqlite数据库内。】

代码目录预览:
预览图1
预览图2

布局目录预览:
预览图3


以下是正文:

主界面布局: 底部使用四个RelativeLayout(学习、社区、消息、我的牛客) + 中间自定义ViewPager(禁止滑动)

主代码写在MainActivity里面,思路:底部四个相对布局(RelativeLayout)相当于四个按钮,点击可跳到ViewPager不同的位置,而ViewPager的每个位置存放了不同的Fragment,因为本身个别Fragment内含有可滑动的ViewPager所以必须取消当前ViewPager的滑动监听以免其内部ViewPager不能响应!

1.自定义ViewPager - CustomViewPager重写onTouchEvent(MotionEvent arg0)和onInterceptTouchEvent(MotionEvent arg0)两个事件

private boolean canScroll;

    public CustomViewPager(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent arg0) {
        if (canScroll) {
            return super.onInterceptTouchEvent(arg0);
        } else {
            return false;
        }

    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent arg0) {
        if (canScroll) {
            return super.onTouchEvent(arg0);
        }else {
            return false;
        }

    }

    /**
     * @param canScroll the canScroll to set
     */
    public void setCanScroll(boolean canScroll) {
        this.canScroll = canScroll;
    }

个人理解
return true:表示当前事件被消费完毕,不会继续向下分发
return false:表示当前事件未被消费完毕,会继续向下分发

2.将4个Fragment放入自定义ViewPager(CustomViewPager)中可以使用FragmentPagerAdapter也可以使用PagerAdapter,这里使用前者。
定义CustomFragementAdapter类继承自FragmentPagerAdapter。
需要传入FragmentManager 和四个Fragment。重写/实现三个方法。

private List<Fragment> fragments;
    public CustomFragementAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

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

    @Override
    public Fragment getItem(int arg0) {
        // TODO Auto-generated method stub
        return fragments.get(arg0);
    }

如果使用的是安卓v4的兼容包MainActivity需要继承自FragmentActivity,FragmentManager需要用getSupportFragmentManager。


接下来就是4个Fragment里面的东西了。
学习:StudyFragment
社区:CommunityFragment(ViewPager + PagerSlidingTabStrip)
消息:MessageFragment (ViewPager + PagerSlidingTabStrip)
我的牛客:ProfileFragment 只有布局不讲解。
上面用到的PagerSlidingTabStrip是第三方的一个组件,貌似安卓某兼容库也有类似功能的(懒得整)。每个Fragment需要继承自Fragment(我用的V4包里的android.support.v4.app.Fragment)。

社区(CommunityFragment)和 消息(MessageFragment )放一起说吧。这两个很相似。都可以用在View中嵌套ListView然后放到ViewPager中的方式实现。

1.以CommunityFragment为例。重写/实现onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)。填充一个View作为返回。

View view = inflater.inflate(R.layout.fragment_community,container,false);

所有视图上的组件用view.findViewById()进行绑定。社区界面有9个滑动界面(刚刚使用了FragmentPagerAdapter)这里使用PagerAdapter进行填充。只要将数据以View的形式传进去就行了。

    private ViewPager pager;
    private PagerSlidingTabStrip mTab;
    private ViewAdapter adapter;
    private ListView[] lv;
    private int mTextColorNormal = Color.BLACK;
    private int mTextColorSelected = Color.parseColor("#ff00bb99");
    private CommunityAdapter cAdapter;

    @SuppressLint("InflateParams")
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_community, container,false);
        pager = (ViewPager)view.findViewById(R.id.communitypager);
        mTab = (PagerSlidingTabStrip) view.findViewById(R.id.communitytabs);
        mTab.setSelectedTextColor(mTextColorSelected);
        mTab.setTextColor(mTextColorNormal);
        mTab.setIndicatorHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()));
        mTab.setIndicatorColor(mTextColorSelected);
        mTab.setBackgroundColor(Color.WHITE);
        mTab.setDividerColor(Color.TRANSPARENT);
        ArrayList<String> titles = new ArrayList<String>();
        titles.add("全部");
        titles.add("技术交流");
        titles.add("笔试面经");
        titles.add("随便聊聊");
        titles.add("站内公告");
        titles.add("资源分享");
        titles.add("我要提问");
        titles.add("招聘信息");
        titles.add("工作感受");
        lv = new ListView[titles.size()];
        List<View> views = new ArrayList<View>();
        List<CommunityItem> data = new ArrayList<CommunityItem>();
        DBManager dbManager = new DBManager(getActivity());
        View mView;
        for (int i = 0; i < 9; i++) {
            mView = LayoutInflater.from(getActivity()).inflate(
                    R.layout.communitylist, null, false);
            data = dbManager.getCommunityItem(i);
            Log.i(TAG, "" + data.size());
            lv[i] = (ListView) mView.findViewById(R.id.commlist);
            cAdapter = new CommunityAdapter(getActivity(), data);
            lv[i].setAdapter(cAdapter);
            Log.i("TAG", "" + cAdapter.getCount());
            views.add(mView);
        }

        adapter = new ViewAdapter(views, titles);
        pager.setAdapter(adapter);
        mTab.setViewPager(pager);
        return view;
    }

有几个滑动页面就需要填充几个View 每一个view需要一个ListView。这里的ListVIew也需要适配器稍后讲。

2.给ViewPager自定义适配器(ViewAdapter)这里我使用的是PagerAdapter。然后把View和标题传进去。

private List<View> views;//View列表
    private List<String> titles;//标题列表
    public ViewAdapter(List<View> views, List<String> titles) {
        this.views = views;
        this.titles = titles;
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(views.get(position));
        //super.destroyItem(container, position, object);
    }

    @Override
    public int getCount() {
        return views.size();
    }

    @Override
    public CharSequence getPageTitle(int position) {
        if (titles != null) {
            return titles.get(position);
        }
        return super.getPageTitle(position);
    }

    @Override
    public View instantiateItem(ViewGroup container, int position) {
        container.addView(views.get(position));
        return views.get(position);
    }
    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
    }

3.上面的每个刚刚说道ListView也需要适配器,自定义适配器(CommunityAdapter)继承自BaseAdapter传入数据和上下文对象。

private List<CommunityItem> data;
    private Context context;

    public CommunityAdapter(Context context, List<CommunityItem> data) {
        this.data = data;
        this.context = context;
    }

    @Override
    public int getCount() {
        return data.size();
    }

    @Override
    public CommunityItem getItem(int position) {
        return data.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    class ViewHolder {

        public ImageView head;
        public TextView name;
        public TextView relayTime;
        public TextView title;
        public TextView summary;
    }

    @SuppressLint("InflateParams")
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = new ViewHolder();
        View view = null;
        if (view == null) {
            view = LayoutInflater.from(context).inflate(
                    R.layout.community_list_item, null, false);
        }

        holder.head = (ImageView) view.findViewById(R.id.head);
        holder.name = (TextView) view.findViewById(R.id.name);
        holder.relayTime = (TextView) view.findViewById(R.id.lastRelayTime);
        holder.title = (TextView) view.findViewById(R.id.title);
        holder.summary = (TextView) view.findViewById(R.id.summary);

        CommunityItem item = data.get(position);
        holder.head.setImageResource(item.getHead());
        holder.name.setText(item.getName());
        String category = "未分类";
        switch (item.getType()) {
        case 1:
            category = "技术交流";
            break;
        case 2:
            category = "笔试面经";
            break;
        case 3:
            category = "随便聊聊";
            break;
        case 4:
            category = "站内公告";
            break;
        case 5:
            category = "资源分享";
            break;
        case 6:
            category = "我要提问";
            break;
        case 7:
            category = "招聘信息";
            break;
        case 8:
            category = "工作感受";
            break;
        default:
            break;
        }
        holder.relayTime.setText(item.getLastRelayTime() + "【" + category
                + "】");
        holder.title.setText(item.getTitle());
        holder.summary.setText(item.getSummary());

        return view;
    }

最后一个部分:StduyFragment只说明“专项学习”(IntelliTestActivity)点进去的界面,这个我使用拓展列表(ExpandableListView)做的适配器使用的是(ExpandableAdapter)继承自BaseExpandableListAdapter

private static final String TAG = "ExpandableAdapter";
    private Context context;
    private List<ExpandableItem> data;

    public ExpandableAdapter(Context context, List<ExpandableItem> data) {
        this.context = context;
        this.data = data;
    }

    @Override
    public int getGroupCount() {
        return data.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return data.get(groupPosition).getItemList().size();
    }

    @Override
    public ExpandableItem getGroup(int groupPosition) {
        return data.get(groupPosition);
    }

    @Override
    public ExpandableSubItem getChild(int groupPosition, int childPosition) {
        return data.get(groupPosition).getItemList().get(childPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        return data.get(groupPosition).getGroupId();
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return data.get(groupPosition).getItemList().get(childPosition)
                .getSubjectId();
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    private TextView catgroy;
    private TextView indicator;

    @SuppressLint("InflateParams")
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
            convertView = LayoutInflater.from(context).inflate(R.layout.expandable_list_item, null);
            catgroy = (TextView)convertView.findViewById(R.id.catgroy);
            indicator = (TextView)convertView.findViewById(R.id.indicator);
        ExpandableItem expand = data.get(groupPosition);
        catgroy.setText(expand.getCatgroy());
        if (isExpanded) {
            indicator.setBackgroundResource(R.drawable.arror_up);
            Log.i(TAG, "" + isExpanded);
        } else {
            indicator.setBackgroundResource(R.drawable.arror_down);
        }

        return convertView;
    }

    private TextView subjectName;
    private TextView subjectTotal;
    private TextView subjectDone;
    private Button exercise;

    @SuppressLint("InflateParams")
    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(
                    R.layout.expandable_sub_list_item, null);
            subjectName = (TextView) convertView
                    .findViewById(R.id.subject_name);
            subjectTotal = (TextView) convertView
                    .findViewById(R.id.subject_total);
            subjectDone = (TextView) convertView
                    .findViewById(R.id.subject_done);
            exercise = (Button) convertView.findViewById(R.id.exercise);

        }
        final ExpandableSubItem item = data.get(groupPosition).getItemList()
                .get(childPosition);
        subjectName.setText(item.getSubjectName());
        subjectTotal.setText("共" + item.getSubjectTotal() + "道题");
        subjectDone.setText("已练习" + item.getSubjectTotal() + "题");
        exercise.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, TestMainActivity.class);
                intent.putExtra("what", item.getSubjectId());//what指的是subject的id,用id去查找相应的题目
                context.startActivity(intent);
            }
        });
        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }

最后的抽题模块:我把它写成了一个类RandomQuestions。可以随机抽出题目,以及题目的选项。

private static final String TAG = "RandomQuestions";
    private Context context;

    public RandomQuestions(Context context) {

        this.context = context;
    }

    /**
     * 
     * @param what
     *            课程类型
     * @param number
     *            需要的题数
     * @return
     */
    public List<QuestionItem> getRadomQuestions(int what, int number) {
        if (number < 1) {
            return null;
        }

        int[] counts = getCounts(number, 11); // 数据库共11题,相当于题目id

        List<QuestionItem> questions = new ArrayList<QuestionItem>();
        DBManager dbManager = new DBManager(context);
        for (int i = 0; i < counts.length; i++) {
            questions.add(dbManager.getQuestion(what, counts[i]));
        }
        return questions;
    }

    /*
     * public static void main(String[] args) {
     * 
     * getCounts(10); }
     */

    /**
     * 随机生成不相同的数组
     * 
     * @param number
     *            所需题目数
     * @param total
     *            题目总数
     * @return
     */
    public static int[] getCounts(int number, int total) {
        int[] counts = new int[number];
        Random random = new Random();
        int index = 0;
        boolean replace = true;
        int c;
        while (index < number) {
            c = random.nextInt(total) + 1;
            for (int i = 0; i < index + 1; i++) {
                if (c == counts[i]) {
                    replace = false;
                    break;
                }
            }
            if (replace) {
                counts[index] = c;
                Log.i(TAG, "counts:" + counts[index]);
                index++;
            }
            replace = true;
        }

        return counts;
    }

项目源码下载地址:
http://download.csdn.net/detail/u013271384/9418443


仿牛客UI(张俊峰) 1.图标来自牛客app 2.大致实现UI效果 3.实现抽提 底部:RelativeLayout(学习、社区、消息、我的牛客) + 中间 自定义ViewPager(禁止滑动) 一、学习界面: (1) 标题模块:牛客 (2) 图片滑动模块:ViewPager+Pager (3) 签到模块:显示(已打卡、今日刷题、今日学习、共打卡) (4) 学习模块:Linearlayout(可用GridView)(专题练习、公司套题、错题练习、课程学习、大题查看、期末备考) ? 点击中任何一个LAYOUT,会显示一个由ExpandableList实现一个列表 ? 点击ExpandabList子标签中的练习字样,会自动跳转到另一个Activity,进行专项练习。 ? 可以进行考试,有倒计时,要求达到牛客网的效果,并能出考试结果。 (5) 参与模块:(文字(我参与的课程)+添加按钮) ? 点击添加按钮跳转到另一页面。由 ListView实现 二、 社区界面: 1. 标题模块:显示文字(最新),点击最新会弹出一个上下文菜单(最新、最热、精华)。 2. 滑动标题模块:ViewPager+PagerSlidingTabStrip 3. 内容模块:使用ListView显示用户内容。 三、 消息界面: 1、 菜单模块:(朋友私信、系统通知)使用ViewPager实现(可用Tabhost) 2、 朋友私信页面:显示一个私信图片 3、 系统通知页面:(由ListView实现)由于比较固定本人使用RelativeLayout实现 四、 我的牛客界面: 1. 头像显示模块:头像+用户名+用户信息 2. 内容显示模块 更多效果请试用,感谢支持!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值