Android高级控件

RecyclerView:

分为两部分:

1.适配器:

创建一个类继承于RecyclerView.Adapter类

        ①条目集:

                在layout文件下面创建一个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="50dp"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_fruit"
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:layout_margin="10dp" />

    <TextView
        android:id="@+id/tv_fruit"
        android:layout_width="70dp"
        android:layout_height="match_parent"
        android:layout_margin="10dp"
        android:padding="5dp" />
</LinearLayout>

       ②适配器类的编写

 创建一个RecyclerView继承于RecyclerView.Adapter,将方法重写,重点在于onCreateViewHolder方法的编写,这个方法主要完成创建ViewHolder的任务,在这个方法里面我们将条目的布局引入,创建一个ViewHolder的实例,将加载出来的布局传入到 构造函数里面,

onBindViewHolder此方法用于对RecyclerView子项数据进行赋值,每个子项被滚动到屏幕里,都会被执行,

getItemCount方法最简单,是用于返回数据源的长度。

这里使用了ViewHolder机制

ViewHolder模式的核心思想是在列表项视图的布局中,使用一个内部类来持有视图控件的引用,以避免重复查找视图的成本。这个内部类通常被命名为ViewHolder

  • 在适配器的getViewonCreateViewHolder方法中,可以使用ViewHolder来查找并持有视图控件的引用。
  • 如果视图已经被创建并持有了控件引用,那么就可以直接使用它们,而不需要重复查找。

 这个是用于持有对控件的引用,对于convertView还有一个是减少对控件的生成,防止内存溢出

最后,数据和控件的绑定在onBindViuViewHolder方法,将由onCreateViewHolder方法传来的holder向下转型为继承RecyclerViewAdapter.ViewHolder类的内部类ViewHolder

package com.example.newhighview.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.example.newhighview.R;
import com.example.newhighview.bean.Fruit;

import java.util.List;

public class RecyclerViewAdapter extends RecyclerView.Adapter {

    private ViewHolder holder;

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView tv;
        ImageView iv;

        public ViewHolder(View view) {
            super(view);
            tv = view.findViewById(R.id.tv_fruit);
            iv = view.findViewById(R.id.iv_fruit);
        }
    }


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_fruit, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }


    private List list;

    public RecyclerViewAdapter(List list) {
        this.list = list;
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        Fruit fruit = (Fruit) list.get(position);
        ViewHolder v = (RecyclerViewAdapter.ViewHolder) holder;
        v.tv.setText(fruit.getTextDesc());
        v.iv.setImageResource(fruit.getPicNum());
    }

    @Override
    public int getItemCount() {
        return list.size();
    }
}

2.实体类:

目的:将每一个条目上的控件作为类的元素,包装成一个类,

由于场景的不同,我们的数据可能来自其他地方,或者已经获取,这里数据已经知道,直接一个for循环放在list集合里面,集合里每一个元素都对应一个条目,需要的数据

package com.example.newhighview.bean;

import android.widget.ImageView;
import android.widget.TextView;

import com.example.newhighview.R;

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

public class Fruit {
    public Fruit() {
    }

    private int picNum;
    private String textDesc;
    public static final int[] picNum1 = new int[]{R.drawable.image1, R.drawable.image2, R.drawable.image3, R.drawable.image4, R.drawable.image5, R.drawable.image6,};
    public static final String[] textDesc1 = new String[]{"这是芒果", "这是苹果", "这是葡萄", "这是火龙果", "这是西瓜", "这是香蕉"};

    static List<Fruit> list;

    public Fruit(int picNum, String textDesc) {
        this.picNum = picNum;
        this.textDesc = textDesc;
    }

    public int getPicNum() {
        return picNum;
    }

    public static List<Fruit> getDefaultList() {
        if (list == null) {
            list = new ArrayList<>();
        }
        //将fruit直接打包成对象
        for (int i = 0; i < picNum1.length; i++) {
            list.add(new Fruit(picNum1[i], textDesc1[i]));
        }
        return list;
    }


    public void setPicNum(int picNum) {
        this.picNum = picNum;
    }

    public String getTextDesc() {
        return textDesc;
    }

    public void setTextDesc(String textDesc) {
        this.textDesc = textDesc;
    }
}

以上两部分完成之后,在活动里,创建LinearLayoutManager类的实例,并传输本活动的的上下文,,并将它设置到recyclerView里面去。

package com.example.newhighview;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;

import com.example.newhighview.adapter.RecyclerViewAdapter;
import com.example.newhighview.bean.Fruit;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RecyclerView recyclerView = findViewById(R.id.Rv);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);
        RecyclerViewAdapter r = new RecyclerViewAdapter(Fruit.getDefaultList());
        recyclerView.setAdapter(r);
    }
}

记得设置适配器。

listView:

和RecyclerView类似,也是用来显示大量数据项的。

listView和RecyclerView在实体类的代码编写上,没有什么区别,应用实际场景决定数据怎么设置,这里我们数据还是那些。

listView适配器:

我们继承BaseAdapter适配器,重写方法,

注意适配器最重要的作用:

        使数据源和条目进行匹配

getView:用来进行绑定数据和条目里的控件,也是ViewHolder派上作用的地方

getCount:返回条目总数

getItem:返回当前条目

getItemId:返回当前条目的个数

我们着重来说getView方法,中代码的编写,

首先通过LayoutInflater类将布局转化为对象,返回对象是一个view

View view = LayoutInflater.from(context).inflate(R.layout.item_fruit, null);

通过这个view调用findViewById找到控件,然后通过操作list集合,将数据和控件绑定起来

        tv = convertView.findViewById(R.id.tv_fruit);
        iv = convertView.findViewById(R.id.iv_fruit);        
        tv.setText(((Fruit) l.get(position)).getTextDesc());
        iv.setImageResource(((Fruit) l.get(position)).getPicNum());

但是这样做有个弊端,如果条目很少,可以在这样做,每出现一个条目,就创建那一套控件的对象。会浪费很大的资源。

因此我们使用一个巧妙的办法,结合ViewHolder模式,使用convertView

convertView 是在 Android 中使用适配器(Adapter)填充 ListViewRecyclerView 等列表控件时经常使用的一个概念。它是一个用于重用已创建的列表项视图的参数或变量,旨在提高性能和减少内存消耗。

具体来说,convertView 是在 getView 方法(对于 ListView)或 onCreateViewHolder 方法(对于 RecyclerView)中用于缓存已经创建的列表项视图的参数。它代表着当前正在处理的列表项视图,这个视图可能已经被创建和绘制,也可能是一个可重用的视图,取决于它是否为空。

在适配器中,你可以使用 convertView 来检查是否有可重用的视图可供使用,如果有,你可以直接将数据绑定到它上面,而不是重新创建一个新的视图。这可以显著提高列表控件的性能,尤其是在大型列表中。

 基本用法:

  1. getView 方法或 onCreateViewHolder 方法中,检查 convertView 是否为空。
  2. 如果 convertView 为空,表示没有可重用的视图,你需要创建一个新的视图并将视图控件的引用存储在一个 ViewHolder 对象中,并将 ViewHolder 对象存储在 convertView 的标签中以备后用。
  3. 如果 convertView 不为空,表示有可重用的视图,你可以从中获取 ViewHolder 对象,并使用它来设置数据。
 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            //如果不为空,则说明没有可用的视图,需要创建新的视图
            convertView = LayoutInflater.from(context).inflate(R.layout.item_fruit, null);
            vh = new ViewHolder();
            tv = convertView.findViewById(R.id.tv_fruit);
            iv = convertView.findViewById(R.id.iv_fruit);
            convertView.setTag(vh);
        } else {
            vh = (ViewHolder) convertView.getTag();
        }
        tv.setText(((Fruit) l.get(position)).getTextDesc());
        iv.setImageResource(((Fruit) l.get(position)).getPicNum());
        return convertView;
    }

对于长列表可以大大提高性能。

在活动中:

不需要布局管理器,直接将适配器设置给listview

注意:

对于listView有一个无法设置条目高度和宽度的问题,这和 RecyclerView有区别,RecyclerView可以直接在条目的根布局上设置条目的高。需要直接设置内部控件的高度,或者重新在原有布局的情况下,设置一个新的布局。

Spinner:

Sipnner指的是下拉列表,

有两种模式:分别是dialog和dropdown

适配器和前面没有区别,使用dropdown模式时候,记得还要重写getDropDwonView方法

ToolBar:

其实就是标题栏,系统默认的是ActionBar,现在我们将它替换为ToolBar,

在theme文件中修改:

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.ActivityTest" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">#0080ff</item>
        <item name="colorPrimaryVariant">#0080ff</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>
</resources>

 注意第二行代码,修改为了NoActionBar,此时系统默认的标题栏就消失了,此时,我们重新搞一个toolbar,

创建menu目录,创建menu resouerce file,

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/backup"
        android:icon="@android:drawable/ic_menu_upload_you_tube"
        android:title="Backup"
        app:showAsAction="always" />
    <item
        android:id="@+id/Delete"
        android:icon="@android:drawable/ic_menu_delete"
        android:title="Delete"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/settings"
        android:icon="@android:drawable/ic_menu_add"
        android:title="settings"
        app:showAsAction="never" />
</menu>

在安卓开发中,showAsAction属性是用于控制菜单项在Action Bar中的显示行为的。Action Bar是Android应用程序中的一个标准界面元素,它通常出现在应用程序的顶部,提供了一个包含应用程序名称、选项菜单和导航按钮的区域。

showAsAction属性可以接受不同的值,用于指定菜单项在Action Bar中的显示方式。以下是showAsAction属性可以接受的值:

  1. alaways:这个值会使菜单项一直显示在ActionBar上。
  2. ifRoom:如果有足够的空间,这个值会使菜单显示在ActionBar上。
  3. never:这个值菜单永远不会出现在ActionBar是。
  4. withText:这个值使菜单和它的图标、菜单文本一起显示。

例如,如果要将一个名为“文件(F)”的菜单项始终显示在Action Bar上,可以将它的showAsAction属性设置为“always”。如果希望将一个名为“编辑(E)”的菜单项永远不会在Action Bar中显示,可以将它的showAsAction属性设置为“never”。

需要注意的是,showAsAction属性是仅在应用程序目标设为蜂巢平台(即Android 3.0)或更高版本时才有效。在较早版本的Android平台上,菜单项需要在选项菜单中手动添加和显示。

活动的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    tools:context="com.example.toolBar.MainActivity">

    <androidx.appcompat.widget.Toolbar
        android:layout_width="match_parent"
        android:id="@+id/tb"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

</FrameLayout>

 活动:

package com.example.toolBar;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.os.Bundle;
import android.view.Menu;

import com.example.newhighview.R;

public class MainActivity extends AppCompatActivity {

    private Toolbar tb;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main4);
        tb = findViewById(R.id.tb);
        setSupportActionBar(tb);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar, menu);
        return true;
    }
}

 将这些菜单显示出来,

 DrawerLayout:

滑动菜单:

这是一种布局,

布局中允许放进去两个直接子控件,第一个子控件是主屏幕显示的内容,第二个子控件显示的是滑动菜单中显示的内容。

因此:

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="#00ff80"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    </FrameLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#fff"
        android:text="This is menu"
        android:textSize="30sp" />


</androidx.drawerlayout.widget.DrawerLayout>

 注意:

其中第二个子空间

layout_gravity属性必须有,而且是start。

关于FrameLayout:

FrameLayout是Android布局中的一种,它是一种简单的布局,通常用于堆叠视图。在FrameLayout中,所有的子视图都被钉在屏幕左上角,这也意味着所有的子视图都被堆叠在一起。

如果你需要更改视图的位置,你可以使用layout_gravity属性。这个属性接受以下值:topbottomleftrightcenter_verticalcenter_horizontalcenter等。

举个例子,以下是一个FrameLayout的使用:

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2"
android:layout_gravity="center" />
</FrameLayout>

在这个例子中,两个按钮都放在FrameLayout中。第一个按钮(Button 1)默认被放在左上角,而第二个按钮(Button 2)则被放在屏幕中心,因为我们使用了layout_gravity="center"

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值