【Android、IOS、Flutter、鸿蒙、ReactNative 】标题栏

831 阅读2分钟

Android 标题栏

Android使用 android:theme 显示标题栏

添加依赖

dependencies {
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.9.0")
   implementation("androidx.constraintlayout:constraintlayout:2.1.4")
}

image.png

配置 android:theme image.png

<application
    ......
    android:theme="@style/Theme.AndroidAppBar"
    ......>
</application>

image.png

Android 自定义标题栏

activity_main.xml布局文件配置ToolBar

<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:layout_constraintTop_toTopOf="parent"
    app:title="自定义 Toolbar"
    app:titleTextColor="@android:color/white" />

image.png

去除标题栏

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.os.Bundle;
import android.view.Window;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 去除标题栏
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);  
        setContentView(R.layout.activity_main);
    }
}

image.png

android:theme="@style/Theme.AndroidAppBar" 主题设置后需要去除标题,不然主题标题栏和自定义标题栏同时存在。

image.png

Android自定义标题栏一

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;

public class MainActivity extends AppCompatActivity {

    private final String TAG = this.getClass().getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);  //去除标题栏
        setContentView(R.layout.activity_main);
        initToolBar();
    }

    private void initToolBar() {
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        toolbar.setNavigationIcon(R.drawable.back);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.i(TAG, "Toolbar Navigation Back");
            }
        });
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Log.i(TAG, "onOptionsItemSelected " + item.getTitle().toString());
        int itemId = item.getItemId();
        if (itemId == R.id.menu_item1) {
            // 处理搜索按钮点击事件
            return true;
        } else if (itemId == R.id.menu_item2) {
            // 处理设置按钮点击事件
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

}

image.png

Compose 标题栏

build.gradle 添加依赖

dependencies {
    ......
    implementation ("androidx.activity:activity-compose:1.3.1")
    implementation("androidx.compose.material:material:1.4.3")
    implementation("androidx.compose.ui:ui-tooling:1.4.3")
}

自定义标题栏

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Menu
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview

class MainComposeActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent { topAppBar() }
    }
}

@Preview
@Composable
fun topAppBar() {
    Scaffold(topBar = {
        TopAppBar(title = { Text(text = "自定义标题栏") }, navigationIcon = {
            IconButton(
                onClick = { /*TODO*/ }) {
                Icon(Icons.Filled.ArrowBack, contentDescription = "Back")
            }
        }, actions = {
            IconButton(onClick = { /*TODO*/ }) {
                Icon(imageVector = Icons.Filled.Menu, contentDescription = "Menu")
            }
        }
        )
    }
    ) { innerPadding ->
        BodyContent1(Modifier.padding(innerPadding))
    }
}
@Composable
fun BodyContent1(padding: Modifier = Modifier) {

}

image.png

IOS Object-c 标题栏 参考

在 SceneDelagate.m 里的如下函数添加根视图控制器:

- (**void**)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    
}
- (**void**)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    ViewController* root = [[ViewController alloc] init];
    UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:root];
    self.window.rootViewController = nav;
}

image.png

自定义标题、返回按钮、菜单按钮

image.png

image.png

image.png

系统默认图标

image.png

image.png

IOS Swift 标题栏

在 SceneDelagate.swift 里的如下函数添加根视图控制器:

image.png

自定义标题、返回按钮、菜单按钮

image.png

image.png

image.png

Flutter 标题栏

pubspec.yaml 里面配置 flutter_screenutil 依赖

image.png

AppBar(
  backgroundColor: const Color(0xff6200EE),
  title: const Text(
    "自定义标题",
    style: TextStyle(color: Colors.white),
  ),
  leading: const Icon(
    Icons.arrow_back,
    color: Colors.white,
  ),
  actions: [
    Padding(
      padding: EdgeInsets.only(right: 20.w),
      child: const Icon(
        Icons.menu,
        color: Colors.white,
      ),
    )
  ],
)

image.png

image.png

鸿蒙 标题栏

import router from '@ohos.router'
/**
 * TitleBar-标题栏
 */
@Preview
@Component
export default struct TitleBar {
  isShow: Boolean = true;//是否有返回按钮  默认:true
  title: string = '' //中间标题
  rightImg: Resource;//右侧图标
  rightTxt: string = '';//右侧文字
  onRightTxtClick?: () => void;//右侧文字点击事件
  onRightImgClick?: () => void;//右侧图标点击事件

  build() {

    Stack() {
      Text(this.title)
        .textAlign(TextAlign.Center)
        .fontColor(Color.White)
        .maxLines(1)
        .fontSize('22fp')

      Row() {
        Image($r('app.media.ic_back'))
          .width('30vp')
          .height('30vp')
          .objectFit(ImageFit.Fill)
          .margin({ left: '10vp' })
          .onClick(() => {
            router.back()
          }).visibility(this.isShow ? Visibility.Visible : Visibility.Hidden)

        Text(this.rightTxt === '' ? '' : this.rightTxt)
          .height('20vp')
          .margin({ right: 20 })
          .fontSize('16fp')
          .fontColor($r('app.color.black'))
          .visibility(this.rightTxt === '' ? Visibility.None : Visibility.Visible)
          .onClick(()=>{
            this.onRightTxtClick();
          })

        Image(this.rightImg === undefined ? null : this.rightImg)
          .width('20vp')
          .height('20vp')
          .margin({ right: 20 })
          .visibility(this.rightImg === undefined ? Visibility.None : Visibility.Visible)
          .onClick(()=>{
            this.onRightImgClick();
          })
      }.width('100%').justifyContent(FlexAlign.SpaceBetween)
    }
    .width('100%')
    .height('60vp')
    .backgroundColor($r('app.color.color_6200EE'))
  }
}

image.png

image.png

image.png

React Native 标题栏

自定义 CustomTitleBar

import React from 'react';
import { View, Text, StyleSheet, Image} from 'react-native';

const CustomTitleBar = ({ title,leftIcon,rightIcon}) => {
  return (
    <View style={styles.container}>
        <View style={styles.iconContainer}>
            <Image source={leftIcon} style={styles.icon} />
        </View>
        <View style={styles.titleBar}>
            <Text style={styles.title}>{title}</Text>
        </View>
        <View style={styles.iconContainer}>
              <Image source={rightIcon} style={styles.icon} />
         </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    width: '100%',
    backgroundColor: '#6200EE',
  },
  iconContainer: {
    padding: 10,
  },
  icon: {
      width: 30,
      height: 30,
      resizeMode: 'contain'
  },
  titleBar: {
    height: 60,
    justifyContent: 'center',
    alignItems: 'center',
    flex:1
  },
  title: {
    color: 'white',
    fontSize: 20,
    fontWeight: 'bold',
  },
});

export default CustomTitleBar;

显示标题栏

import {AppRegistry} from 'react-native';
import {name as appName} from './app.json';

import React from 'react';
import { View, Text } from 'react-native';
import CustomTitleBar from './CustomTitleBar';

const MyApp = () => {
  return (
    <View style={{ flex: 1 }}>
      <CustomTitleBar title="我的标题"
       leftIcon={require('./assets/ic_back.png')}
        rightIcon={require('./assets/ic_menu.png')}/>
    </View>
  );
};

AppRegistry.registerComponent(appName, () => MyApp);

image.png

案例

切换到 分支 flutter_appbar