类微信界面AS开发(一)

1,911 阅读8分钟

一:实验目的及完成后界面展示

使用AS,完成一个Like-WeChat界面的开发,这次主要是对ui和界面转换的完成。

下方按钮分别为消息,好友,通讯录,设置,所在页面对应的按钮为绿色,其余为灰色

先展示下完成结果:

二:ui方面的具体实现

首先在可以在阿里矢量图标库下载图标(这个没要求,喜欢什么图都可以),需要注意的是下载图标时记得选择图标大小,不然默认的200大小的图标巨大。。。还不好调,建议选择35大小。

图标下载好后,开始进行xml界面的书写,我们可以分成三个部分:顶部,底部以及中间区域。

1.顶部xml

顶部的配置比较简单,只需要在LinearLayout(vertical)里书写一个textview,配置下大小,颜色,位置即可。具体代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="65dp"
    android:background="#000000"
    android:gravity="center"
    android:orientation="vertical">
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/app_name"
        android:textColor="#ffffff"
        android:textSize="20sp" />
</LinearLayout>

代码分析:

因为做的是顶部的xml,所以需要对layout的高度进行限定,防止全屏显示,所以会有android:layout_height="65dp"

为了使”LikeWeChat“文本居中,对layout和textview都进行gravity的选择

最后使标题背景为黑色,标题为白色,#000000为黑 #ffffff为白

android:background="#000000"
android:textColor="#ffffff"

完成后结果如下:

2.底部xml

底部xml主要是四个图标及他们对应的文字描述。

这一部分我们应该要考虑到后面对图标和文字的点击反应,应该把对应的图标和文字放在同一个layout里,再将4个对应不同图标文字的layout放在一个大的layout里。

我们可以简化思路,先只写其中一个,然后其余三个可以直接copy再改部分内容就行。以其中的“聊天”为例:

  • 第一步,我们再AS里的xml编辑页面,选择Design模式,直接在可视化界面上拖动LinerLayout到界面里,这个作为大的背景。把它的orientation选择为horizontal水平方向布局,这一步是因为接下来要将四个图标文字水平方向均匀分布,我们还需要把它的背景设置为我们下载的矢量图标:bottom_bar.9.png,同时,与顶部xml一样,我们需要规定它的高度,将baselineAligned设置为false 阻止布局对齐其子级的基线。这部分代码如下:

    android:layout_width="match_parent"
    android:layout_height="80dp"
    android:background="@drawable/bottom_bar"
    android:orientation="horizontal"
    android:baselineAligned="false"
    
  • 第二步,我们再拖一次LinerLayout,这一次放在第一步创建的大的layout下,作为它的子部分,它的作用就是作为“聊天”的图片和对应文字的容器,便于之后的点击响应。它的orientation选择为vertical垂直方向布局,这是因为图片和文字在子容器里是垂直方向的布局,然后gravity选择center放在中心。别忘了给它一个id便于之后的java编写调用。这一部分代码如下:

    android:id="@+id/id_tab_weixin"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:gravity="center"
    android:orientation="vertical"
    
  • 第三步,我们先进行图片的插入,直接在控件栏里选择ImageView拖入。然后在弹出来的页面里选择对应的图标。再给图标背景色设置为黑色#000000,并设置为不可点击,具体代码如下:

    <ImageButton
        android:id="@+id/id_tab_weixin_img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#000000"
        android:clickable="false"
        android:contentDescription="@string/app_name"
        android:src="@drawable/tab_weixin_pressed" />
    
  • 第四步,插入textView,直接在控件栏里选择textView拖入到与ImageView同级目录下,设置文字大小及中心位置center,因为背景是我们下载的图标(灰黑色),所以这里将文字字体设置为白色#ffffff,同样,不可点击,具体代码如下:

    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:gravity="center"
        android:layout_height="wrap_content"
        android:text="微信"
        android:clickable="false"
        android:textColor="#ffffff"
        android:textSize="15sp" />
    
  • 第五步就很简单了,直接将聊天对应的layout进行复制粘贴到4份,这个时候效果如下:

  • 第六步,我们只需要改一下图标,文本以及id,就完成了底部xml的配置,修改后效果:

3.activity_main.xml

activity_main.xml有些特殊,它是作为主要调动的xml文件,因此,它需要导入顶部xml与底部xml,可以通过include layout导入,然后中间部分使用fragment,这样在进行页面的转换时,顶部和底部是不会变的,变化的只有中间。具体代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/top" />

    <FrameLayout
        android:id="@+id/id_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    </FrameLayout>

    <include layout="@layout/bottom" />
</LinearLayout>

可以看到,fragment的范围是除了top与bottom以外的所有空间

4.中间部分文字xml

这一部分就很简单了,只需要自己创建4个xml文件,里面加入textView,写上自己先显示的文字就行,格式、大小啥的都可以自己为所欲为。这里就不展示了

三:界面通信java部分编写

在开始正式编写之前,这里有个小细节,一般我们打开安卓虚拟机时,顶部会带有项目名称的title,类似这种:

就很丑。。。那么我们可以通过命令:

supportRequestWindowFeature(Window.FEATURE_NO_TITLE);

隐藏title。

(ps:这里有个坑,如果你的MainActivity继承的是AppCompatActivity,那么上面的这个语句就是正确的,但当你继承的是Activity,你就需要去掉support)

效果如下:

步入正题

这部分的一个重点知识就是fragment与FragmentManage,我们可以这样理解,我们刚刚编写的四个中间部分显示文字的xml就相当于4个fragment,然后我们在new一个FragmentManage作为通信的控制器。

1.Fragment及FragmentManage配置

首先新建4个Fragment,直接右键->new->fragment->fragment(blank)

AS会为我们自动生成,我们只需要在里面修改onCreateView()里的组件id为我们创建的4个文本xml,如:

return inflater.inflate(R.layout.tab01, container, false);

然后在主函数里声明4个fragment,代码如下:

private Fragment mTab01 = new weixinFragment();
private Fragment mTab02 = new frdFragment();
private Fragment mTab03 = new contactFragment();
private Fragment mTab04 = new settingsFragment();

声明完后,我们还需要一个FragmentManage来对Fragment的通信进行控制

private FragmentManager fm;

2.调入fragment

调入fragment我们需要对它进行初始化,也就是将4个文本xml添加进去然后提交,代码如下:

private void initFragment(){
    fm = getSupportFragmentManager();
    FragmentTransaction transaction = fm.beginTransaction();
    transaction.add(R.id.id_content, mTab01);
    transaction.add(R.id.id_content, mTab02);
    transaction.add(R.id.id_content, mTab03);
    transaction.add(R.id.id_content, mTab04);
    transaction.commit();
}

3.调入各控件

同样的,我们只需要对之前声明的各个控件进行初始化就行,代码如下:

private void initView(){
    mTabWeixin = findViewById(R.id.id_tab_weixin);
    mTabFrd = findViewById(R.id.id_tab_frd);
    mTabContact = findViewById(R.id.id_tab_contact);
    mTabSettings = findViewById(R.id.id_tab_settings);

    mImgWeixin = findViewById(R.id.id_tab_weixin_img);
    mImgFrd = findViewById(R.id.id_tab_frd_img);
    mImgContact = findViewById(R.id.id_tab_contact_img);
    mImgSettings = findViewById(R.id.id_tab_settings_img);
}

4.隐藏Fragment

因为当我们点击图标时,我们希望只显示对应的文本内容,隐藏不想关的,我们换一个思路,开始我们就全部隐藏,只有当点击时,才让它显示出来,隐藏fragment的函数需要用到.hide()。我们通过FragmentManage进行通信控制,所以需要传fm的参数。

具体代码如下:

private void hideFragment(FragmentTransaction transaction){
    transaction.hide(mTab01);
    transaction.hide(mTab02);
    transaction.hide(mTab03);
    transaction.hide(mTab04);
}

5.选择fragment显示相对应的界面

这里我们需要实现的是,当我们点击到对应范围时,显示对应的fragment,可以用到switch-case函数和fragment.show()函数进行显示。

(ps:这里因为我们开始我们就隐藏全部的fragment,只有当点击时,才让它显示出来,所以需要用到show函数)

代码如下:

private void selectFragment(int i){
    FragmentTransaction transaction = fm.beginTransaction();
    // 实现全部隐藏
    hideFragment(transaction);
    // 设置内容区域,当选择时,才让它显示
    switch (i){
        case 0:
            transaction.show(mTab01);
            // 同时将底部的图片显示为选择状态的颜色
            mImgWeixin.setImageResource(R.drawable.tab_weixin_pressed);
            break;
        case 1:
            transaction.show(mTab02);
            mImgFrd.setImageResource(R.drawable.tab_find_frd_pressed);
            break;
        case 2:
            transaction.show(mTab03);
            mImgContact.setImageResource(R.drawable.tab_address_pressed);
            break;
        case 3:
            transaction.show(mTab04);
            mImgSettings.setImageResource(R.drawable.tab_settings_pressed);
            break;
        default:
            break;
    }
    // 提交
    transaction.commit();
}

6.编写select函数

上面说到,当我们选择不同的layout时,显示对应的内容与图标,使用的是switch-case函数

那么怎么传给selectFragment对应的int 数值进行switch呢?

这个时候,我们就需要编写相关的函数,将点击不同的子类layout(即4各图标及它们对应的文字部分)时传递不同的值给selectFragment()。可以使用getID函数进行switch-case。

代码如下:

public void onClick(View view) {
    resetImg();
    switch (view.getId()){
        case R.id.id_tab_weixin:
            selectFragment(0);
            break;
        case R.id.id_tab_frd:
            selectFragment(1);
            break;
        case R.id.id_tab_contact:
            selectFragment(2);
            break;
        case R.id.id_tab_settings:
            selectFragment(3);
            break;
    }
}

这里我们注意到还有一个resetImg(),

这就是我们下面要讲的。

7.重置图标

当我们点击完一个图标,我们再点击另外的图标时,我们希望前面点击过的图标重新变为之前的颜色(样式)。不然当我们点击一次后,图标将永远保持显示状态,这是我们不希望的。

因此,我们需要重置图标,需要写一个resetImg函数。然后将它放在onClick函数开始,表示每一次click时,实现将图标初始化。具体代码如下:

public void resetImg(){
    mImgWeixin.setImageResource(R.drawable.tab_weixin_normal);
    mImgContact.setImageResource(R.drawable.tab_address_normal);
    mImgFrd.setImageResource(R.drawable.tab_find_frd_normal);
    mImgSettings.setImageResource(R.drawable.tab_settings_normal);
}

8.最后一步,指定事件范围

当我们就按照上面的代码执行时,这个时候,我们不管点击哪个位置,都是一次锚点,也就是说,即使我们点击的不是底部的按钮,它仍然会进行一次switch-case对锚点进行位置判定。这是极其消耗资源的。

因此,我们需要指定事件的判定范围:只有点击bottom时才进行锚点判断。具体代码如下:

private void initEvent(){
    mTabWeixin.setOnClickListener(this);
    mTabContact.setOnClickListener(this);
    mTabFrd.setOnClickListener(this);
    mTabSettings.setOnClickListener(this);
}

至此,全部代码讲解完毕。

项目源码地址:gitee.com/White-9/Lik…

(博客可能写的还存在很多问题,后期会逐步修改的。)