Android Studio设计微信门户框架

目录

作业目标

技术说明

环境准备

主要技术

图片准备

关键代码解析

top.xml(头部文件):

bottom.xml(底部文件):

activity_main.xml(基本布局文件):

fragment.xml(中间布局文件):

item.xml(列表项布局):

MainActivity.java:

fragment1.java,fragment2.java,fragment3.java,fragment4.java(对应fragment布局文件):

Album.java:

Myadapter2.java:

运行效果

实验心得

源码


作业目标

  1. 设计一个app的门户框架,需要实现3-4个tab切换效果。实现一个类似微信的布局,包括聊天、通讯录、发现和设置4个页面。本功能要求需要的技术为:activity、xml、fragment。
  2. 在任一tab页中实现列表效果,我选择在tab1(聊天页面)实现一个左边是图标、右边是文本的列表。本功能的实现需要使用recyclerview。

技术说明

环境准备

在MyApplication2项目中完成项目基础搭建,安装了SDK和AVD以供实验顺利运行。

主要技术

  1. Activity组件:为应用程序提供生命周期管理,允许应用程序在不同状态下执行操作;展示应用程序的用户界面,使用户通过这些界面和应用程序进行交互;启动其他的组件,使得不同的组件直接可以进行通信和协作。
  2. Fragment:包含在Activity中,更好地适应不同屏幕尺寸和设备类型,提供更一致的用户体验。
  3. Wiget控件:主要使用了TextView控件(用于显示字符)、ImageView控件(用于显示图像)。

图片准备

将该项目需要的图标图片上传到目录MyApplication2\app\src\main\res\drawable下,便于调用。需要注意的是图片的文件名中不能使用大写字母,否则会在构建或运行时遇到问题。

关键代码解析

  • top.xml(头部文件):

在layout中创建头部文件,添加一个TextView,输入文本“微信”,文本颜色修改为白色,LinearLayout背景颜色修改为黑色,文本大小调整为50sp并居中。

具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/black">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="微信"
        android:textAlignment="center"
        android:textColor="@color/white"
        android:textSize="50sp" />

</LinearLayout>

效果如下:

  • bottom.xml(底部文件):

首先调整文件布局:在已有的LinearLayout(horizontal)下添加LinearLayout(vertical),在LinearLayout(vertical)下添加一个imageView和一个textView,将LinearLayout(vertical)复制粘贴3次,生成4个水平的LinearLayout。

然后,我在imageView中使用了之前上传到drawable中的图片,textView中分别填入“聊天”、“通讯录”、“发现”和设置,修改各种参数使4个LinearLayout及其内部的图片和文本能够排列整齐。

最后为4个LinearLayout及其图片与文本设置各自的id,便于之后的调用。

具体代码如下:

最外层LinearLayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
</LinearLayout>

内层LinearLayout(聊天页面的LinearLayout1为例):一开始使用了AS自带的样例图片,运行时会失败和报错,因此要使用自己上传的图片。

<LinearLayout
        android:id="@+id/LinearLayout1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/jjh" />

        <TextView
            android:id="@+id/textView11"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="聊天"
            android:textSize="30sp" />

    </LinearLayout>

效果如下:

  • activity_main.xml(基本布局文件):

首先调整文件布局:将LinearLayout布局设置为vertical,然后用include把top.xml和buttom.xml添加到activity_main1.xml中,再添加FrameLayout,使页面中间能够显示需要的文本。

然后修改各控件的参数:添加FrameLayout的id为content,layout_width设置match_parent、layout_height设置为match_parent、layout_weight设置为1,从而让FrameLayout布满父布局的所有可用空间。

具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity1">

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

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

    </FrameLayout>

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

效果如下:

fragment.xml(中间布局文件):

为了类微信布局的设计,我们需要创建4个不同的fragment.xml文件,分别表示出用户当前所处的页面。

以下是我创建的4个文件:fragment1.xml展示聊天页面,fragment2.xml展示通讯录页面,fragment3.xml展示发现页面,fragment4.xml展示设置页面。

分别添加textView并且修改各种参数,另外在fragment1.xml中添加一个recyclerView,因为我需要在聊天页面中实现列表效果。

具体代码如下:

fragment1.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="center"
        android:text="聊天界面"
        android:textColor="#009688"
        android:textSize="60sp" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="15" />

</LinearLayout>

效果如下:

fragment2.xml(其他3个除了id和文本内容以外没有区别):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_weight="1"
        android:gravity="center"
        android:text="通讯录界面"
        android:textSize="60sp" />
</LinearLayout>

效果如下:

item.xml(列表项布局):

为想要输出的列表进行布局的设计,我选择左边显示图标,右边显示文本的布局,因此LinearLayout布局方式为horizontal,然后存入一个imageView和一个textView,并且调整各种参数。

预览时我发现我准备导入的图片有点大,所以把imageView的layout_width和layout_height调整为100dp。

具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_weight="1" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="20"
        android:gravity="center"
        android:text="TextView"
        android:textSize="40sp" />

</LinearLayout>

效果如下:

MainActivity.java:

MainActivity类继承Activity类,并且添加implements View.OnClickListener。

  • 首先创建Fragment类的实例对象,定义FragmentManager对Fragment进行控制,以及用于监听的变量:
    // Fragment类的实例对象
    Fragment fragment1,fragment2,fragment3,fragment4;
    // FragmentManager
    FragmentManager fm;
    // 设置交互控件的变量
    LinearLayout linearLayout1,linearLayout2,linearLayout3,linearLayout4;
  • onCreate()函数(初始化activity):从activity_main1.xml文件中,添加需要找到的LinearLayout(bottom.xml中的4个linearlayout控件),然后初始化fragment实例对象并且调用fragment页面的展示函数fragmentshow(),最后用setOnClickListener()对添加的4个linearlayout作全局的点击监听。
// Activity的初始化
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main1);

        linearLayout1=findViewById(R.id.LinearLayout1);
        linearLayout2=findViewById(R.id.LinearLayout2);
        linearLayout3=findViewById(R.id.LinearLayout3);
        linearLayout4=findViewById(R.id.LinearLayout4);

        fm=getSupportFragmentManager();
        fragment1=new Fragment1();
        fragment2=new Fragment2();
        fragment3=new Fragment3();
        fragment4=new Fragment4();

        initial();
        fragmentshow(fragment1);

        // 在当前类有全局的点击监听
        linearLayout1.setOnClickListener(this);
        linearLayout2.setOnClickListener(this);
        linearLayout3.setOnClickListener(this);
        linearLayout4.setOnClickListener(this);
    }
  • fragmenthide()函数:因为4个页面需要分别显示,所以需要隐藏fragment中定义的content。在这里使用FragmentTransaction来管理fragment的隐藏。
    // 隐藏不需要显示的content
    private void fragmenthide() {
        FragmentTransaction ft=fm.beginTransaction()
                .hide(fragment1)
                .hide(fragment2)
                .hide(fragment3)
                .hide(fragment4);
        ft.commit();
    }
  • fragmentshow()函数:使用FragmentTransaction来管理每个fragment的显示,函数的意义是先调用前面设计好的fragmenthide()函数,将4个fragment都隐藏起来,然后再显示我们希望显示的fragment。
    // 展示所需要的content
    private void fragmentshow(Fragment fragment) {
        // 先隐藏所有的content,再显示出需要的content
        fragmenthide();
        FragmentTransaction ft=fm.beginTransaction()
                .show(fragment);
        ft.commit();
    }
  • initial()函数:一个初始化函数,把4个fragment放到ft中,实现页面的切换。
    // 定义初始化函数
    private void initial() {
        // 把fragment加入content
        FragmentTransaction ft =fm.beginTransaction()
                .add(R.id.content,fragment1)
                .add(R.id.content,fragment2)
                .add(R.id.content,fragment3)
                .add(R.id.content,fragment4);
        // 事务的完整性以提交commit为准
        ft.commit();
    }
  • onClick()函数:用于监听被点击的图标,并根据此显示对应页面的内容。一开始我使用的是switch case语句进行分类,但是在我的AS上会一直报错“constant expression required”,即使定义静态常量l1=R.id.LinearLayout也无法解决,因此换成if语句进行分类讨论。
    @Override
    public void onClick(View view) {
        // 获取控件变量的id,然后决定点击监听
        if (view.getId()==R.id.LinearLayout1){
            fragmentshow(fragment1);
        }
        if (view.getId()==R.id.LinearLayout2){
            fragmentshow(fragment2);
        }
        if (view.getId()==R.id.LinearLayout3){
            fragmentshow(fragment3);
        }
        if (view.getId()==R.id.LinearLayout4){
            fragmentshow(fragment4);
        }

    }

fragment1.java,fragment2.java,fragment3.java,fragment4.java(对应fragment布局文件):

首先继承fragment类。

  • fragment1.java:

创建全局变量recyclerview和ma

    RecyclerView recyclerView;
    Myadapter2 ma;

onCreateView():创建视图,与fragment1.xml关联,然后通过findViewById获取recyclerView的视图,通过setLayoutManager设置recyclerView的布局管理器。然后将列表需要的图片及其文本添加进Album类和list,最后调用适配器Myadapter2关联recyclerView,使列表内容能在fragment1中显示。

        View view=inflater.inflate(R.layout.fragment1, container, false);
        recyclerView=view.findViewById(R.id.recyclerView1);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

        // 把图片及其名称存入类Album
        List<Album> list = new ArrayList();
        Album thestorybegins = new Album(getRandomLengthName("The Story Begins"), R.drawable.tsb);
        list.add(thestorybegins);
        Album pagetwo = new Album(getRandomLengthName("Page Two"), R.drawable.cheerup);
        list.add(pagetwo);
        Album lane1 = new Album(getRandomLengthName("Twicecoaster:Lane1"), R.drawable.tt);
        list.add(lane1);
        Album lane2 = new Album(getRandomLengthName("Twicecoaster:Lane2"), R.drawable.knock);
        list.add(lane2);
        Album signal = new Album(getRandomLengthName("Signal"), R.drawable.sig);
        list.add(signal);
        Album twicetagram = new Album(getRandomLengthName("Twicetagram"), R.drawable.likey);
        list.add(twicetagram);
        Album merryhappy = new Album(getRandomLengthName("Merry&Happy"), R.drawable.mh);
        list.add(merryhappy);
        Album whatislove = new Album(getRandomLengthName("What Is Love"), R.drawable.wil);
        list.add(whatislove);
        Album summernights = new Album(getRandomLengthName("Summer Nights"), R.drawable.sn);
        list.add(summernights);
        Album yesoryes = new Album(getRandomLengthName("YES or YES"), R.drawable.yoy);
        list.add(yesoryes);
        Album fancyyou = new Album(getRandomLengthName("FANCY YOU"), R.drawable.fancy);
        list.add(fancyyou);
        Album feelspecial = new Album(getRandomLengthName("Feel Special"), R.drawable.fs);
        list.add(feelspecial);
        Album moremore = new Album(getRandomLengthName("MORE&MORE"), R.drawable.mm);
        list.add(moremore);
        Album eyeswideopen = new Album(getRandomLengthName("Eyes Wide Open"), R.drawable.ewo);
        list.add(eyeswideopen);
        Album tasteoflove = new Album(getRandomLengthName("Taste Of Love"), R.drawable.tol);
        list.add(tasteoflove);
        Album formulaoflove = new Album(getRandomLengthName("Formula Of Love:O+T=<3"), R.drawable.fol);
        list.add(formulaoflove);
        Album between12 = new Album(getRandomLengthName("BETWEEN 1&2"), R.drawable.ttt);
        list.add(between12);
        Album readytobe = new Album(getRandomLengthName("READY TO BE"), R.drawable.rtb);
        list.add(readytobe);

        // 适配器
        ma=new Myadapter2(list);
        recyclerView.setAdapter(ma);

        return view;

getRandomLengthName():将需要的文本转换为字符串,存入Album类和list中。如果不使用getRandomLengthName()函数,将会存在关于字符类型的报错。

    // 将专辑名转换为string
    private String getRandomLengthName(String name){
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 1; i++) {
            builder.append(name);
        }
        return builder.toString();
    }
  • fragment2.java(fragment3和fragment4与fragment2相同):

onCreateView():创建并返回了与Fragment2.xml关联的布局视图,将其添加到container中,false参数表示不要立即将布局添加到container中,而是允许后续的逻辑来处理它。

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState){
        return inflater.inflate(R.layout.fragment2, container, false);
    }

Album.java:

存放列表的每张图片和每个文件,使列表能够通过适配器存入fragment1。

package com.example.myapplication;

// 存放专辑的名称和图片
public class Album {
    private String name;
    private int imageid;
    public Album(String name,int imageid){
        this.name=name;
        this.imageid=imageid;
    }

    public String getName() {
        return name;
    }

    public int getImageid() {
        return imageid;
    }
}

Myadapter2.java:

  • 首先定义一个Album类型的list1,然后通过Myadapter2函数传入list的值:
    private List<Album> list1;

    // 传入值
    public Myadapter2(List list) {
        list1=list;
    }
  • onCreateViewHolder():创建viewHolder,使用from函数生成静态压缩器,然后把数据填入viewHolder并返回。
    @NonNull
    @Override
    public Viewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // 压缩器(from生成静态压缩器)
        // 闪退时可以挂布尔值false运行
        View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.item1,parent,false);
        Viewholder viewholder=new Viewholder(view);
        return viewholder;
    }
  • onBindViewHolder():得到list1中存放的数据,存入每个子项holder中。
    @Override
    public void onBindViewHolder(@NonNull Viewholder holder, int position) {
        Album album=list1.get(position);
        // 获取专辑的名称和封面图片
        holder.textView.setText(album.getName());
        holder.imageView.setImageResource(album.getImageid());
    }
  • getItemCount():返回list1的长度(行数)。
    @Override
    public int getItemCount() {
        return list1.size();
    }
  • 内嵌类holder:相当于一个行指针。
    // 内嵌类 holder类似一个行指针
    static class Viewholder extends RecyclerView.ViewHolder{
        View view;
        // 存放专辑名称
        TextView textView;
        // 存放专辑封面
        ImageView imageView;

        public Viewholder(@NonNull View itemView) {
            super(itemView);
            view=itemView;
            // item1.xml中的控件对象
            textView=itemView.findViewById(R.id.textView4);
            imageView=itemView.findViewById(R.id.imageView);
        }
    }

运行效果

 

动态效果:

实验心得

通过本次实验,我初次接触到了AS项目的开发,在无数次遇到错漏和解决问题的过程中,终于完成了这个类微信的门户页面设计项目。这使我对Android的各种基本功能和运行模式、以及各个文件和控件直接的关联与逻辑有了清晰的理解,也记住了activity和fragment的生命周期和运行时会产生的各种状态。

源码

存储在gitee:test1: 作业1:app门户页面设计与开发

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用android studio 运行,下面是一个简单的文档,这个代码是一个demo 一、Activity的使用 1、SNActivity 框架最基本的activity,可调用$(SNManager)进行操作activity,具体用法请参考文档或代码 2、SNNavigationSlidingActivity 包含SNActivity的功能,继承于com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivity 支持导航条和左滑视图的Activity 加载导航条: loadNavBar(int height,int background_color_id) loadNavBarResId(int height_id,int background_id) 加载左侧视图: /** * load left view * @param left_id left layout id * @param offset_value offset value * @param shadow_width_value shadow width value * @param shadow_drawable_id shadow drawable style * @param fade fade value */ loadLeft(int left_id, int offset_value, int shadow_width_value, int shadow_drawable_id, float fade) /** * load left view * @param left_id left layout id * @param offset_id offset id * @param shadow_width_id shadow width id * @param shadow_drawable_id shadow drawable id * @param fade fade value */ loadLeftResId(int left_id, int offset_id, int shadow_width_id, int shadow_drawable_id, float fade) 二、SNElement的使用 View的伪装对象,支持所有View的功能,详细功能可参考文档或代码 手动伪装:$.create $.id $.findView 注入伪装:$.setContent(view class or layout id,inject class); 获取原型:elem.toView(); 三、注入 1、视图注入 A、创建注入类,属性名称必须和layout中的id对应,如果不对应请加入标签@SNInjectView class DemoInject{ @SNInjectView(id=R.id.tvTest) public SNElement test; } B、实例化注入对象 DemoInject di=new DemoInject(); C、调用$.inject或者$.setContent注入 $.inject(di); D、注入成功后即可调用对象 String text=di.test.text(); 2、依赖注入 A、需要绑定注入对象,建议写到Application中的onCreate SNBindInjectManager.instance().bind(ITest.class, Test.class); B、与视图注入不同的是属性必须添加标签@SNIOC,注入的对象(Test)必须包含只有一个SNManager参数的构造函数,且必须实现注入者 public class Test implements ITest{ SNManager $; public Test(SNManager _$){ this.$=_$; }; } class DemoInject{ @SNIOC public ITest test; } C、调用$.inject或者$.setContent注入 同视图注入 D、注入成功后即可调用对象 di.test.xxx(); 四、fragment的使用 1、SNFragment 2、SNLazyFragment 五、控件的使用 1、SNFragmentScrollable 2、SNPercentLinearLayout、SNPercentRelativeLayout 3、SNScrollable 4、SNSlipNavigation 5、XList 6、slidingtab
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值