android 仿Boss直聘消息界面

最近好久没有更新我的博客了,之前5月份由于在一家苦逼的初创公司,一直有时间更新blog,上周离职了,好好休息了两天,上周面了一家公司感觉挺好的,这两天一边找工作一边写写博客吧。祝我顺利等到offer吧^_^(不过北京这一段时间的Android行情不是特别好啊)
好了,开始今天的主题,在找工作用的是Boss直聘,感觉APP里面的消息界面还不错,就试着自己写了一个。以后有时间把其他界面也写一下,先看一下GIF效果。
这里写图片描述
接下来简单说一下吧!
先来看一下main布局文件吧,比较简单,先看一下图片
这里写图片描述
直接看代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.cxy.boss.ui.MainActivity">
    <RadioGroup
        android:id="@+id/main_rg"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        android:weightSum="4" >
        <RadioButton
            android:id="@+id/rb_find_nor"
            android:layout_height="match_parent"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:button="@null"
            android:checked="true"
            android:drawableTop="@drawable/rb_find_nor_selecter"
            android:text="职位"
            android:textSize="12sp"
            android:gravity="center"/>
        <RadioButton
            android:id="@+id/rb_company"
            android:layout_height="match_parent"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:button="@null"
            android:drawableTop="@drawable/rb_company_selecter"
            android:text="公司"
            android:textSize="12sp"
            android:gravity="center"/>
        <RadioButton
            android:id="@+id/rb_message"
            android:layout_height="match_parent"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:button="@null"
            android:drawableTop="@drawable/rb_message_selecter"
            android:text="消息"
            android:textSize="12sp"
            android:gravity="center"/>
        <RadioButton
            android:id="@+id/rb_myPage"
            android:layout_height="match_parent"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:button="@null"
            android:drawableTop="@drawable/rb_my_selecter"
            android:text="我的"
            android:textSize="12sp"
            android:gravity="center"/>
    </RadioGroup>
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#cacaca"
        android:id="@+id/line"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="60dp"
        />
    <FrameLayout
        android:id="@+id/id_ll_top"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">
    </FrameLayout>
</RelativeLayout>

底部导航是一个RadioGroup ,里面有四个RadioButton,根据radioButton 的状态来动态切换四个Fragment达到切换页面的效果。在布局文件里的RadioButton的背景是
‘’android:drawableTop="@drawable/rb_message_selecter"我们再来看一下rb_message_selecter.xml这个文件。

这里写图片描述
drawable包下,有四个rb开头的文件,我们来看一下rb_message_selecter文件,一共三行主要代码,第一行是item被选中的时候要显示的图片资源,第二行是未被选中时显示的图片资源,第三行显示的是默认显示的图片资源。

接下来看一下MainActivity文件
MainActivity.java

package com.cxy.boss.ui;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.KeyEvent;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.cxy.boss.R;
import com.cxy.boss.fragment.Company_Fragment;
import com.cxy.boss.fragment.Find_Fragment;
import com.cxy.boss.fragment.Message_Fragment;
import com.cxy.boss.fragment.My_Fragment;

public class MainActivity extends FragmentActivity implements RadioGroup.OnCheckedChangeListener {

    static long exittime = 0;                        //计算两次Back键按下的时间
    private RadioGroup group;
    private FragmentManager manager;    //Fragmnet的管理器
    private FragmentTransaction transaction;    //Fragment事物
    private My_Fragment my_fragment;        //我的页面
    private Find_Fragment find_fragment;    //职位页面
    private Company_Fragment company_fragment;  //公司页面
    private Message_Fragment message_fragment;  //消息页面


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    /**
     * @程序功能:布局初始化
     * @autho:cxy
     * */
    private void initView() {
//        findById
        group = (RadioGroup) findViewById(R.id.main_rg);
        manager = getSupportFragmentManager();
        transaction = manager.beginTransaction();
        //对RadioGroup设置监听
        group.setOnCheckedChangeListener(this);
        //职位的Fragmnet
        find_fragment = new Find_Fragment();
        //公司的Fragmnet
        company_fragment = new Company_Fragment();
        //消息的Fragmnet
        message_fragment = new Message_Fragment();
        //我的Fragment
        my_fragment = new My_Fragment();
        //为事物添加布局页面
        transaction.add(R.id.id_ll_top,find_fragment);
        transaction.add(R.id.id_ll_top,company_fragment);
        transaction.add(R.id.id_ll_top,message_fragment);
        transaction.add(R.id.id_ll_top,my_fragment);
//        隐藏收藏和我的界面
        transaction.hide(company_fragment);
        transaction.hide(my_fragment);
        transaction.hide(message_fragment);
//        提交事物
        transaction.commit();
        //为group设置监听
        group.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
        //根据RaidoButton切换对应的页面
        transaction = manager.beginTransaction();
        switch (checkedId){
            case R.id.rb_find_nor:
                transaction.show(find_fragment);
                transaction.hide(company_fragment);
                transaction.hide(message_fragment);
                transaction.hide(my_fragment);
                break;
            case R.id.rb_company:
                transaction.show(company_fragment);
                transaction.hide(find_fragment);
                transaction.hide(message_fragment);
                transaction.hide(my_fragment);
                break;
            case R.id.rb_message:
                transaction.show(message_fragment);
                transaction.hide(company_fragment);
                transaction.hide(find_fragment);
                transaction.hide(my_fragment);
                break;
            case R.id.rb_myPage:
                transaction.show(my_fragment);
                transaction.hide(company_fragment);
                transaction.hide(message_fragment);
                transaction.hide(find_fragment);
                break;
            default:
                break;
        }
        //提交事务
        transaction.commit();
    }
    //监听返回键
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK){
            this.exitapp();
        }
        return true;
    }

    /**
     * 程序从功能:
     *          退出程序
     * **/
    private void exitapp() {
        if ((System.currentTimeMillis() - exittime)>2000){
            Toast.makeText(this,"再按一次返回键退出程序",Toast.LENGTH_SHORT).show();
            exittime = System.currentTimeMillis();
        }else{
            System.exit(0);
        }
    }
}

代码里注释比较详细,在这里就不多解释了,这样就大概构成了boss直聘的最基本框架,下面来看一下Message_Fragment.java这个文件,

package com.cxy.boss.fragment;


import android.graphics.Color;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import com.cxy.boss.R;

import java.util.ArrayList;
import java.util.List;

/**
 * 消息
 * Created by cxy on 2016/11/14.
 */

public class Message_Fragment extends Fragment implements View.OnClickListener{

    private ViewPager viewPager;
    //顶部的聊天、互动的button
    private Button btn_chat,btn_exchange;
//    聊天的Fragment
    private Msg_chat_Fragment msg_chat_fragment;
    //互动的Fragment
    private Msg_exchange_Fragment msg_exchange_fragment;
//    fragment的容器
    private List<Fragment> fragments;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view =  inflater.inflate(R.layout.fragment_message,null);
        initView(view);
        initPager();
        return view;
    }
    /**
     * 布局初始化
     * */
    private void initView(View view) {
        btn_chat = (Button)view. findViewById(R.id.btn_chat);
        btn_exchange = (Button)view. findViewById(R.id.btn_exchange);
        viewPager = (ViewPager)view. findViewById(R.id.msg_vp);
        btn_chat.setOnClickListener(this);
        btn_exchange.setOnClickListener(this);
    }
    //监听聊天和互动的点击事件
    @Override
    public void onClick(View view) {
        switch (view.getId()){
            //如果是聊天的Button点击
            case R.id.btn_chat:
                //设置viewPager选中第1个页面
                viewPager.setCurrentItem(0);
                btn_chat.setTextColor(Color.rgb(83,202,195));
                btn_chat.setBackgroundColor(Color.rgb(255,255,255));
                btn_exchange.setTextColor(Color.rgb(255,255,255));
                btn_exchange.setBackgroundColor(Color.rgb(83,202,195));
                break;
            // 如果是互动的Button点击
            case R.id.btn_exchange:
                //设置viewPager选中第2个页面
                viewPager.setCurrentItem(1);
                // 设置文字颜色和button背景色
                btn_exchange.setTextColor(Color.rgb(83,202,195));
                btn_exchange.setBackgroundColor(Color.rgb(255,255,255));
                btn_chat.setTextColor(Color.rgb(255,255,255));
                btn_chat.setBackgroundColor(Color.rgb(83,202,195));
                break;
        }
    }
    /**
     * 初始化ViewPager
     * */
    private void initPager(){
        fragments = new ArrayList<Fragment>();
        msg_chat_fragment = new Msg_chat_Fragment();
        msg_exchange_fragment = new Msg_exchange_Fragment();
        fragments.add(msg_chat_fragment);
        fragments.add(msg_exchange_fragment);
        //设置适配器
        viewPager.setAdapter(new MyPagerAdapter(getFragmentManager()));
        //设置viewPager的监听
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                //根据position的值来改变顶部button的切换。文字颜色和背景颜色
                if (position==0){
                    btn_chat.setTextColor(Color.rgb(83,202,195));
                    btn_chat.setBackgroundColor(Color.rgb(255,255,255));
                    btn_exchange.setTextColor(Color.rgb(255,255,255));
                    btn_exchange.setBackgroundColor(Color.rgb(83,202,195));
                }else{
                    btn_exchange.setTextColor(Color.rgb(83,202,195));
                    btn_exchange.setBackgroundColor(Color.rgb(255,255,255));
                    btn_chat.setTextColor(Color.rgb(255,255,255));
                    btn_chat.setBackgroundColor(Color.rgb(83,202,195));
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }
//    viewPager适配器
    class MyPagerAdapter extends FragmentPagerAdapter {

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }

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

注释比较详细,就不做过多解释了。
再来看一下消息的Fragment文件

package com.cxy.boss.fragment;


import android.graphics.Color;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.cxy.boss.R;

import java.util.ArrayList;
import java.util.List;

/**
 * 互动页面
 * Created by cxy on 2016/11/14.
 */

public class Msg_exchange_Fragment extends Fragment implements View.OnClickListener{

    //申明ViewPager
    private ViewPager vp;
    //申明相关组件
    private TextView tv_likeMe;
    private TextView tv_seeMe;
    private TextView tv_newJob;
    private List<Fragment> fragments;
    //对我有意,谁看过我,新职位的Fragment
    private Exc_Likeme_Fragment likeMeFragment;
    private Exc_Seeme_Fragment seeMeFragment;
    private Exc_newJob_Fragment newJobFragment;
//    定义必要变量和组件
//    看到width这个变量, 是用来控制绿色线条的宽度,与Display、LayoutParams 配合使用。
    private int width;
    private Display mDisplay;
    private LinearLayout.LayoutParams params;
    private View mViewLine;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view =  inflater.inflate(R.layout.fragment_msg_exchange,null);
        initView(view);
        return view;
    }
    /**
     * 布局初始化
     * */
    private void initView(View view) {
        fragments = new ArrayList<>();
        likeMeFragment = new Exc_Likeme_Fragment();
        seeMeFragment = new Exc_Seeme_Fragment();
        newJobFragment = new Exc_newJob_Fragment();
        //像list里添加fragment
        fragments.add(likeMeFragment);
        fragments.add(seeMeFragment);
        fragments.add(newJobFragment);
//        findID
        vp = (ViewPager) view.findViewById(R.id.exce_vp);
        mViewLine = (View)view.findViewById(R.id.tab_line);
        tv_likeMe = (TextView) view.findViewById(R.id.tv_likeMe);
        tv_seeMe = (TextView) view.findViewById(R.id.tv_seeMe);
        tv_newJob = (TextView) view.findViewById(R.id.tv_newJob);
        //设置监听
        tv_likeMe.setOnClickListener(this);
        tv_seeMe.setOnClickListener(this);
        tv_newJob.setOnClickListener(this);
        //设置适配器
        vp.setAdapter(new MyPagerAdapter(getFragmentManager()));
//        获取当前窗口的display
        mDisplay  = getActivity().getWindowManager().getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        mDisplay.getMetrics(outMetrics);
        width = outMetrics.widthPixels/3;
        params = (LinearLayout.LayoutParams)mViewLine.getLayoutParams();
        params.width = width;
        mViewLine.setLayoutParams(params);
        vp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if(positionOffset != 0 && positionOffsetPixels != 0 ){
                    params.leftMargin = positionOffsetPixels / fragments.size() + width * position ;
                    mViewLine.setLayoutParams(params);
                }
            }
//            根据选择的状态给便能字体颜色
            @Override
            public void onPageSelected(int position) {
                switch (position){
                    case 0:
                        tv_likeMe.setTextColor(Color.rgb(153,153,153));
                        tv_seeMe.setTextColor(Color.rgb(187,187,187));
                        tv_newJob.setTextColor(Color.rgb(187,187,187));
                        break;
                    case 1:
                        tv_seeMe.setTextColor(Color.rgb(153,153,153));
                        tv_likeMe.setTextColor(Color.rgb(187,187,187));
                        tv_newJob.setTextColor(Color.rgb(187,187,187));
                        break;
                    case 2:
                        tv_newJob.setTextColor(Color.rgb(153,153,153));
                        tv_seeMe.setTextColor(Color.rgb(187,187,187));
                        tv_likeMe.setTextColor(Color.rgb(187,187,187));
                        break;
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
    }

    /**
     * 对顶部的Tab的TextView设置监听来改变选中
    * 的字体颜色和设置ViewPager到与点击项相匹配的position
      */
    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.tv_likeMe:
                vp.setCurrentItem(0);
                tv_likeMe.setTextColor(Color.rgb(153,153,153));
                tv_seeMe.setTextColor(Color.rgb(187,187,187));
                tv_newJob.setTextColor(Color.rgb(187,187,187));
                break;
            case R.id.tv_seeMe:
                vp.setCurrentItem(1);
                tv_seeMe.setTextColor(Color.rgb(153,153,153));
                tv_likeMe.setTextColor(Color.rgb(187,187,187));
                tv_newJob.setTextColor(Color.rgb(187,187,187));
                break;
            case R.id.tv_newJob:
                vp.setCurrentItem(2);
                tv_newJob.setTextColor(Color.rgb(153,153,153));
                tv_seeMe.setTextColor(Color.rgb(187,187,187));
                tv_likeMe.setTextColor(Color.rgb(187,187,187));
                break;
        }
    }
//    适配器
    class MyPagerAdapter extends FragmentPagerAdapter {

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }

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

相关解释都写在代码里了,现在来分析一下。
看到width这个变量, 是用来控制红色线条的宽度,与Display、LayoutParams 配合使用。
pageCount主要是用来计算当前滑动的时候, 线条的左右边距。
解题思路: 主要操作其实就是那条红色的提示线。 当我们在滚动ViewPager的 时候, 只需要能够动态的操作提示线的左边距属性MarginLeft即可。

所以我们需要对ViewPager提供滚动的监听器, 其主要操作的方法就是public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
理解属性:
position,当前选中的页面位置(从0开始);
positionOffset, 大小从0到屏幕宽度或从屏幕宽度到0。 取决于你的左右滑动状态。
positionOffsetPixels,
主要就是对我们手指状态的一个操作。 值为1的时候, 正在滑动、 2: 手指抬起, 0: 结束了。
开始进入算法逻辑:
在我们的onPageScrolled中的处理,
首先我们需要保证当前的ViewPager处于可滑动状态。 否则就不要进行逻辑处理了,不然消费太大。
然后我们已经提前获取到了提示线的LayoutParams对象(不要在该方法啊中获取LayoutParams,
不然非常浪费内存) 。
params.leftMargin
= positionOffsetPixels / pageCount + width * position ; 可以看出我们一直在不停的给MarginLeft计算值
然后mViewLine.stLayoutParams(params);不停的进行绘制,
这样可以有一种类似于动画的效果体现。
计算:
positionOffsetPixels / pageCount: 我们有三个页面, 这样计算可以正常的分配每个Tab占有的屏幕宽度值;width * position : width为提示线宽度, 这个值基本上就不需改变了。 position前面解释过意思了。 这样可以计算出我的当前MarginLeft的所需宽度大小。 (之后一直setLayoutParams就可以了。)
基本的逻辑都是比较清晰的, 也非常的容易懂。 (不喜请喷!!!)
最后放上demo的地址:
http://download.csdn.net/detail/xiaoyu940601/9868389

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值