layout: post
title: 安卓开发(一)环境搭建、基本程序与控件
description: 安卓开发(一)环境搭建、基本程序与控件
tag: 安卓


文章目录

  • Intent:协助应用间的交互与通信
    • intent书写两个activity页面跳转:
    • intent带数据
    • Activity带参数返回
  • Activity的生命周期
    • 当有两个activity时的执行顺序:
  • View视图
  • 布局
    • 相对布局
  • Fragment
    • 静态fragment构建步骤
    • 动态fragment构建步骤
    • fragment通信
      • Activity调用Fragment
      • Fragment中获取所在Activity
      • 谷歌官方fragment接口通信
  • 横屏竖屏判断
  • 全局变量配置
  • 真机测试
  • 生成apk安装包的方法
  • inflater(布局填充器)
  • 基本控件
    • 按钮
    • ImageView
    • 进度条
    • 按钮组
    • 对话框dialog
  • Menu
    • 选项菜单
    • 弹出菜单
    • 上下文菜单
    • 动作条actionView
    • ListView

Intent:协助应用间的交互与通信

根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。
Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。因此,可以将Intent理解为不同组件之间通信的“媒介”专门提供组件互相调用的相关信息。

intent书写两个activity页面跳转:

也可以在manifest.xml中activity中的action来实现跳转:


当xml配置文件中action名有重名时,会由用户选择执行哪一个。

intent带数据

使用Bundle 存储数据,再将bundle传到intent中(bundle.putExtras()):

在要切换到的activity中通过getIntent.getExtras(),获取到传来的bundle,取出内容:

Activity带参数返回


这种的activity之间传参是双向的:
具体实现在发送方主要是:

接收方接收到信息进行处理,反馈数据给发送方


发送方接收到反馈信息后,确认请求码和接收码,编写回调。
整个过程类似http通信。

Activity的生命周期

当有两个activity时的执行顺序:

View视图



布局

相对布局

Fragment

fragment类似Vue的组件




静态fragment构建步骤

fragment类似vue中封装的小组件。
1-在activity中使用fragment占位,(需要注意填写fragment的name属性,指明fragment所在位置)
2-编写fragment具体的layout.xml文件
3-编写fragment对应的java类,在onCreatView中采用inflater填充器将fragment的layout文件填充到View

动态fragment构建步骤

直接编写好fragment的layout文件和java类文件,然后在activity中
使用fragment管理器:在main_activity中:

fragment通信

Activity调用Fragment

Activity在onCreate()中对fragment进行了渲染加载,因此可以直接在onStart()中直接获取fragment中的元素来处理事件。

Fragment中获取所在Activity

一般在Fragment的onActivityCreate中获取到所在Activity

注意:findViewById方法只在activity中可以使用
在fragment中onCreateView先填充view:

然后view有findViewById方法

谷歌官方fragment接口通信

一般来讲,最好的事件处理方法是fragment各自监听本身的控件,监听到事件后,把事件统一交给activity处理,
因此需要在fragment与activity中设置接口,传递事件。

单纯考虑fragment自己的监听和回调,步骤即为设置监听,以及监听到事件后回调执行。
而现在的做法是fragment中监听,监听到事件后在activity中执行,因此首先在fragment中定义一个接口interface来包裹fragment中对事件的监听,即抽象出fragment层的监听,该抽象也需要定义设定,而interface就是桥梁,interface在activity中实现,activity在onAttachFragment即装载fragment时,如遇到有监听的fragment,则将该fragment对事件的监听收归自己所有,具体而言就是通过设定interface将自身引入传用,执行监听到事件后的回调操作,至此完成activity对fragment中监听事件的通信。

这种做法的好处在于,在fragment中完成监听以后,可以交给不同的activity来复用,interface可以看做是对fragment的监听功能的一种封装打包,将其打包给activity使用。

步骤详解:
在fragment中定义监听事件接口和设置监听事件(“定义监听事件接口”,具体是指监听的执行,即监听谁,而设定监听事件,则是完成对监听事件的传出设置)设定接口方法,设定接口方法可将接口中传递的事件私有化到activity本身。

在activity中实现该接口(即,监听到事件后对事件的处理):

在fragment中进行设置监听(依旧是在onActivityCreate()方法下)


在onAttachFragment()中,即给activity装载fragment时,判断是否装载的是所需的fragment,如何是,将该fragment实例化,并实例化设置接口方法
这里要注意,前边在fragment中只是定义了接口的设置,这里才是真正调用了所定义的方法,完成了接口对事件的实例化。因为Activity中实现了fragment的接口方法,所有activity本身即是监听事件。


activity获取了fragment的对事件的监听,执行回调。

横屏竖屏判断

全局变量配置

项目开发的过程中,可能会大量的使用全局变量,在android开发中,大多数人更偏向于使用application来保存全局变量。Application类是用来维护应用程序全局状态。我们可以提供自己的实现,并在AndroidManifest.xml文件的标签中指出它的名字,这将导致在创建应用程序时去实例化我们自己的Application类。Android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例模式的一个类。且Application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局唯一的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以,通过Application来进行一些数据传递、数据共享、数据缓存等操作。

首先创建继承自Application的MyApplication类,定义变量score,并创建get和set方法。
复制代码

package com.example.whs.myapplication;import android.app.Application;/*** Created by whs on 17/5/1.*/public class MyApplication extends Application {private int score = 100;public int getScore() {return score;}public void setScore(int score) {this.score = score;}
}

下面就是如何使用我们创建的全局变量了,在MainActivity中,首先要获得MyApplication的对象,因为MyApplication继承自Application,所以使用getApplication()方法即可,然后可以调用MyApplication的get或set方法进行访问全局变量。

        MyApplication application = (MyApplication)this.getApplication();application.setScore(200);int score = application.getScore()

真机测试

手机端:查看手机安卓版本,比如安卓11.0,开启开发者模式(一般是系统管理、关于手机、版本信息、软件版本),进入开发者选项(进入开发者模式后设置中出现),打开USB调试。
电脑端:根据手机安卓版本,下载对应的SDK平台(设置中)

一般还需要给手机下载谷歌的USB驱动,在SDKtools中:

根据下载的位置:D:\Jetbrains\andriodSDK\extras\google\usb_driver,更新驱动程序。

所有都做完后,一般可以检测到安卓设备。

生成apk安装包的方法

生成apk

inflater(布局填充器)

布局渲染的过程:
获取填充器,构建布局View,编辑View属性

LayoutInflater inflater = getLaoutInflater();
View layout = inflater.inflate(R.layout.custom,(ViewGroup)findViewById(R.id.llToast));
TextView title = layout.findViewById(R.id.tvTitleToast);
image.setImageResource(R.drawble.picture);

基本控件

按钮

按钮的快速绑定三部曲:
1- 在主类中实现监听方法
2- 设置按钮监听器
3- 重写onClick()按钮点击的回调。

ImageView

ImageView具有setImageDrawable()和getDrawable()来设置图像内容或者获取图像内容。

进度条

设置水平进度条:

    <ProgressBarandroid:id="@+id/id_progress"style="?android:attr/progressBarStyleHorizontal"android:layout_width="match_parent"android:layout_height="wrap_content" />
                // 设置进度条mProgressBar.setProgress(mProgress);

按钮组

            <RadioGroupandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_marginEnd="20dp"android:id="@+id/rd_mode_set"android:orientation="horizontal"><RadioButtonandroid:id="@+id/bt_set_mode_normal"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/bt_set_mode_normal" /><RadioButtonandroid:id="@+id/bt_set_mode_sos"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/bt_set_mode_sos" /><RadioButtonandroid:id="@+id/bt_set_mode_extreme"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/bt_set_mode_extreme" /></RadioGroup>
        rg_mode_set = findViewById(R.id.rd_mode_set);rg_mode_set.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Override// 第一个参数 按钮组,第二个被选中按钮的idpublic void onCheckedChanged(RadioGroup radioGroup, int i) {for (Map.Entry<String, Integer> entry : MODE_MAP.entrySet()) {if (Objects.equals(entry.getValue(), i)) {try {String cmd = getCMDDownMode('1',Integer.parseInt(entry.getKey()));writeCh.setValue(cmd.getBytes("GBK"));gatt.writeCharacteristic(writeCh);} catch (Exception e) {e.printStackTrace();}}}}});

对话框dialog

点击显示对话框

    /*** 修改头像选择*/private void selectImg(){AlertDialog.Builder builder = new AlertDialog.Builder(this).setTitle("提示").setMessage("请选择操作类型").setPositiveButton("拍照", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {try {Intent intent = new Intent(ActivityUser.this,TakePhoto.class);startActivityForResult(intent, 12);}catch (Exception e){e.printStackTrace();}}}).setNegativeButton("图库", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {addPic();}}).setNeutralButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {}});builder.create().show();}

Menu

选项菜单

basic activity:

布局构成:
工具栏+content+浮动按钮
content使用的include引入的另一个layout资源文件:

具体的菜单选项内容在menu文件夹下定义。
orderInCategory,是设定选项的顺序。
可以添加icon图标

menu的每个item选项可以再嵌套menu:

在java类中,先在onCreateOptionsMenu()中使用getMenuInflater()对菜单进行填充
在onOptionsItemSelected()中设置菜单选项点击时的回调。


当然构建menu时也可以为每个setting设置onClick事件
如果有设置,则系统优先执行的是你设置的onClick,而不是onOptionsItemSelected()中的回调。

弹出菜单

在activity中实现视图点击监听和弹出菜单点击监听。

创建PopupMenu对象,填充菜单内容,设置监听,在onMenuItemClick中写回调。

上下文菜单

浮动模式
菜单可以动态添加
menu.add()


菜单选项监听:

动作模式
顶部动作选项


引入actionMode

创建actionMode对象:
先判断actionMode是否已经执行,避免多次生成;
然后设置
startActionMode
需要传递actionModeCallback参数,就是执行actionMode的回调

actionModeCallback需要另行构造
在onCreateActionMode中填充菜单
onActionModeItemClicked中写点击回调

动作条actionView

以内置的searchView类型动作按钮为例:


ListView

ListView本身在layout中只是占位用,实际内容需另外构建item.xml文件。
比较简单的使用,数据类型比较单一的时候,listview占位:

item.xml,只有一个TextView

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="18sp"android:padding="5dp"
/>

activity中;
使用ArrayAdapter填充item.xml,给listview设置adapter,adapter添加数据。

        //初使化设备适配器存储数组mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);mUnPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);//设置已配队设备列表ListView pairedListView = findViewById(R.id.pairedListView);pairedListView.setAdapter(mPairedDevicesArrayAdapter);pairedListView.setOnItemClickListener( mDeviceClickListener);// 设置新查找设备列表ListView newDevicesListView = findViewById(R.id.unPairedListView);newDevicesListView.setAdapter(mUnPairedDevicesArrayAdapter);newDevicesListView.setOnItemClickListener(mDeviceClickListener);//         得到本地蓝牙句柄mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
//        //添加已配对设备到列表并显示if (pairedDevices.size() > 0) {findViewById(R.id.pairedListView).setVisibility(View.VISIBLE);for (BluetoothDevice device : pairedDevices) {mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());}} else {String noDevices = "没有找到已配对的设备。" ;mPairedDevicesArrayAdapter.add(noDevices);}

较为复杂的实现,adapter需要自己定义。

例如聊天界面的消息列表
listview占位不赘述。
itme的xml形式:
主要包括气泡框,发送时间,头像,发送内容这些数据。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout style="@style/jmui_chat_item_send_layout"xmlns:android="http://schemas.android.com/apk/res/android"><TextViewandroid:id="@+id/tv_sendtime"style="@style/jmui_chat_text_date_style"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:gravity="right"android:orientation="horizontal"><ImageButtonandroid:id="@+id/jmui_fail_resend_ib"android:layout_width="21dp"android:layout_height="21dp"android:layout_gravity="center_vertical"android:layout_marginRight="5dp"android:background="@drawable/send_message_failed"android:clickable="true"android:scaleType="fitCenter"android:visibility="gone"/><LinearLayoutstyle="@style/jmui_msg_content_style"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="3dp"android:autoLink="web"android:background="@drawable/jmui_msg_send_bg"android:paddingLeft="10dp"android:paddingRight="18dp"android:textColor="#363333"android:textColorLink="#157BFB"android:orientation="vertical"><TextViewstyle="@style/jmui_msg_text_style"android:id="@+id/tv_content"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColorLink="#157BFB"android:visibility="visible"/><ImageViewstyle="@style/jmui_msg_img_style"android:id="@+id/iv_content"android:adjustViewBounds="true"android:layout_width="wrap_content"android:layout_height="wrap_content"android:visibility="gone"/></LinearLayout><LinearLayoutandroid:id="@+id/ll_push"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="3dp"android:background="@drawable/business_card_bg"android:orientation="vertical"android:visibility="gone"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"><ImageViewandroid:id="@+id/iv_push_img"android:layout_width="40dp"android:layout_height="40dp"android:layout_marginBottom="12.33dp"android:layout_marginLeft="11dp"android:layout_marginTop="13.33dp"/><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="14dp"android:orientation="vertical"><TextViewandroid:id="@+id/tv_menuName"android:layout_width="120dp"android:layout_height="wrap_content"android:layout_marginLeft="11.33dp"android:ellipsize="end"android:maxLines="1"android:textColor="#2C2C2C"android:textSize="15sp"/><TextViewandroid:id="@+id/tv_pushContent"android:layout_width="120dp"android:layout_height="wrap_content"android:layout_marginLeft="11.33dp"android:layout_marginTop="4dp"android:ellipsize="end"android:maxLines="1"android:textColor="#999999"android:textSize="12sp"/></LinearLayout></LinearLayout><Viewandroid:layout_width="183dp"android:layout_height="0.33dp"android:layout_marginLeft="10dp"android:layout_marginRight="16.67dp"android:background="#DCDCDC"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="3dp"android:layout_marginLeft="10dp"android:layout_marginTop="3dp"android:text="@string/Message_push"android:textColor="#989898"android:textSize="10sp"/></LinearLayout><ImageViewandroid:id="@+id/jmui_avatar_iv"style="@style/jmui_chat_item_sender_avatar_style"android:layout_width="@dimen/avatar_list_size"android:layout_height="@dimen/avatar_list_size"android:scaleType="fitCenter"android:gravity="center_vertical" />
<!--        <TextView-->
<!--            android:id="@+id/default_head"-->
<!--            android:layout_width="@dimen/default_head_list"-->
<!--            android:layout_height="@dimen/default_head_list"-->
<!--            android:layout_marginEnd="10dp"-->
<!--            android:textSize="@dimen/default_head_list_text"-->
<!--            android:textColor="@color/white"-->
<!--            android:gravity="center"-->
<!--            android:background="@drawable/border_head_list"/>--></LinearLayout></LinearLayout>
package com.beidouapp.model.adapters;import static androidx.core.content.ContextCompat.startActivity;
import static com.beidouapp.model.utils.ImageUtil.getDefaultBitmap;
import static com.beidouapp.model.utils.ImageUtil.isImage;import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;import androidx.activity.result.contract.ActivityResultContracts;import com.alibaba.fastjson.JSON;
import com.beidouapp.Config;
import com.beidouapp.R;
import com.beidouapp.model.messages.ChatMessage;
import com.beidouapp.model.messages.Position;
import com.beidouapp.model.utils.ImageUtil;
import com.beidouapp.ui.ZoomPhoto;
import com.beidouapp.ui.ZoomPosition;
import com.beidouapp.ui.ZoomVideo;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;public class ChatAdapter extends BaseAdapter {List<ChatMessage> chatMessageList;LayoutInflater inflater;Context context;public ChatAdapter(Context context, List<ChatMessage> list) {this.chatMessageList = list;this.context = context;inflater = LayoutInflater.from(context);}@Overridepublic int getViewTypeCount() {return 2;}@Overridepublic int getItemViewType(int position) {if (chatMessageList.get(position).getIsMeSend() == 1)return 0;elsereturn 1;}@Overridepublic int getCount() {return chatMessageList.size();}@Overridepublic Object getItem(int position) {return chatMessageList.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {String fileName;ChatMessage chatMessage = chatMessageList.get(position);String content = chatMessage.getContent();
//        int start=content.lastIndexOf("/");
//        int end=content.lastIndexOf(".");
//        if(start!=-1 && end!=-1){//            fileName = content.substring(start+1,end);
//        }else{//            fileName = null;
//        }
//        Log.d("zw", "getView: " + content + " " + fileName + ".amr");String extraContent = "File//sdcard/BeidouAPP/Download/" + "2d46ee8c-69ab-445f-b960-7ec3b56672e3" + ".amr";Log.d("zw", "getView: " + extraContent);String time = formatTime(chatMessage.getTime());String type = chatMessage.getType();String nickname = chatMessage.getName();int isMeSend = chatMessage.getIsMeSend();String avatar = chatMessage.getAvatar();String id = chatMessage.getId();//int isRead = chatMessage.getIsRead();final ViewHolder holder;if (convertView == null) {holder = new ViewHolder();if (isMeSend == 0) {convertView = inflater.inflate(R.layout.item_chat_receive_text, parent, false);holder.tv_content = convertView.findViewById(R.id.tv_content);holder.tv_sendtime = convertView.findViewById(R.id.tv_sendtime);holder.iv_content = convertView.findViewById(R.id.iv_content);holder.tv_display_name = convertView.findViewById(R.id.tv_display_name);holder.avatar = convertView.findViewById(R.id.tv_display_avatar);} else {convertView = inflater.inflate(R.layout.item_chat_send_text, parent, false);holder.tv_content = convertView.findViewById(R.id.tv_content);holder.iv_content = convertView.findViewById(R.id.iv_content);holder.tv_sendtime = convertView.findViewById(R.id.tv_sendtime);holder.avatar = convertView.findViewById(R.id.jmui_avatar_iv);}convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}if (avatar.equals(holder.avatar.getTag())){}else {ImageUtil.loadAvatar(context, id, avatar, holder.avatar);holder.avatar.setTag(avatar);}holder.tv_sendtime.setText(time);if (type.equals("text")) {holder.tv_content.setVisibility(View.VISIBLE);holder.tv_content.setText(content);holder.iv_content.setVisibility(View.GONE);}else if (type.equals("img")) {try {holder.tv_content.setVisibility(View.GONE);Bitmap bitmap = BitmapFactory.decodeFile(content);holder.iv_content.setImageBitmap(bitmap);holder.iv_content.setVisibility(View.VISIBLE);holder.iv_content.setOnClickListener(view -> {Intent intent = new Intent(context, ZoomPhoto.class);intent.putExtra("path",content);context.startActivity(intent);});} catch (Exception e) {holder.tv_content.setVisibility(View.VISIBLE);holder.tv_content.setText("[图片已损坏]");holder.iv_content.setVisibility(View.GONE);}}else if (type.equals("audio")) {holder.tv_content.setVisibility(View.GONE);holder.iv_content.setImageResource(R.drawable.icon_voice_press);holder.iv_content.setVisibility(View.VISIBLE);holder.iv_content.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {try {MediaPlayer mediaPlayer = MediaPlayer.create(context, Uri.parse(content));mediaPlayer.start();
//                        MediaPlayer mediaPlayer = MediaPlayer.create(context, Uri.parse(extraContent));
//                        mediaPlayer.start();}catch (Exception e){Log.d("zw", "onClick: 此时使用第二个方法加载");try {MediaPlayer mediaPlayer = MediaPlayer.create(context, Uri.parse(extraContent));mediaPlayer.start();}catch (Exception exception){Log.d("zw", "onClick: 第二个方法也错了");exception.printStackTrace();}}}});}else if (type.equals("video")) {try {holder.tv_content.setVisibility(View.GONE);MediaMetadataRetriever media = new MediaMetadataRetriever();media.setDataSource(content);Bitmap baseBitmap = media.getFrameAtTime();holder.iv_content.setImageBitmap(ImageUtil.getVideoImg(context, baseBitmap));holder.iv_content.setVisibility(View.VISIBLE);holder.iv_content.setOnClickListener(view -> {Intent intent = new Intent(context, ZoomVideo.class);intent.putExtra("path",content);Log.d("视频", "getView: "+content);context.startActivity(intent);});} catch (Exception e) {holder.tv_content.setVisibility(View.VISIBLE);holder.tv_content.setText("[视频已损坏]");holder.iv_content.setVisibility(View.GONE);}}else if (type.equals("notice")) {holder.tv_content.setVisibility(View.VISIBLE);holder.tv_content.setText("群公告:"+ content);holder.iv_content.setVisibility(View.GONE);}else if (type.equals("pos")) {holder.tv_content.setVisibility(View.VISIBLE);holder.iv_content.setVisibility(View.VISIBLE);Position pos = JSON.parseObject(content, Position.class);holder.tv_content.setText("位置:" + pos.getText());holder.iv_content.setImageResource(R.drawable.pos_img);holder.iv_content.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(context, ZoomPosition.class);intent.putExtra("pos", pos);context.startActivity(intent);}});}if (isMeSend == 1) {}else{holder.tv_display_name.setVisibility(View.VISIBLE);holder.tv_display_name.setText(nickname);}return convertView;}class ViewHolder {private TextView tv_content;private TextView tv_sendtime;private TextView tv_display_name;private ImageView avatar;private ImageView iv_content;//private TextView tv_isRead;}private String formatTime(String timeMillis) {long timeMills=Long.parseLong(timeMillis);SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date date = new Date(timeMills);return simpleDateFormat.format(date);}
}

这个adapter的编写思路:

1- public class ChatAdapter extends BaseAdapter
然后实现方法:
四个方法分别是获取列表长度,根据位置索引获取到某个item,根据位置索引获取itme的id,获取视图

2-构建子类viewHolder用于声明item中的各个布局组件

3- alt+inser,选择‘construct’,构造方法,开放接口给activity,以便输出context和数据列表:
这里还传输了inflater,是为了渲染item.xml

4-在getview中,使用inflater渲染item.xml,并实例化viewHolder中的各个布局组件,进行数据设置。

5-在activity中使用自定义adapter:

    /*** 更新消息列表*/private void initChatMsgListView() {adapter = new ChatAdapter(context, chatMessageList);listView.setAdapter(adapter);listView.setSelection(chatMessageList.size());listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);}

这里 listView.setSelection(chatMessageList.size());将列表选中最后一个item,
listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
如果是 TRANSCRIPT_MODE_ALWAYS_SCROLL:则 强制 从 ListView 的底部开始刷新;
如果是 TRANSCRIPT_MODE_NORMAL:如果当前的最后一个 Item 在 ListView 显示范围内,adapter 数据集内容变化时就从滚动底部;否则不滚动到底部!

安卓开发(一)环境搭建、基本程序与控件相关推荐

  1. 【炼丹术士的从零开始的安卓开发】Day1 项目结构与一些控件的学习

    关于老版项目导入的一些问题 import android.support.v4.XXX或者import android.support.v7.XXX出错解决办法 import android.supp ...

  2. 小程序开发及环境搭建及发布

    一.小程序开发及环境搭建 1.下载Hbuild X https://www.dcloud.io/hbuilderx.html 2.下载腾讯开发工具 https://q.qq.com/wiki/tool ...

  3. HarmonyOS(鸿蒙系统)物联网开发教程——环境搭建

    HarmonyOS(鸿蒙系统)物联网开发教程--环境搭建 目录 HarmonyOS(鸿蒙系统)物联网开发教程--环境搭建 前言 1 HarmonyOS简介 2 开发环境搭建 2.1 简洁版环境搭建(使 ...

  4. BI报表开发之环境搭建(二)

    上一篇<BI报表开发之环境搭建(一)>中详细描述了SQL SERVER R2 的安装步骤,本篇将继续描述BI报表开发的环境搭建部分-- Orale数据库安装. <1>下载ora ...

  5. auto.js id为参数滑动_【Autojs教程】02Autojs PC端开发调试环境搭建

    [Autojs教程]02-Autojs PC端开发调试环境搭建 写在前面 本篇教程算是保姆级教程了,希望以此能吸引更多感兴趣的同学学习Autojs,也希望大家能因此碰撞出更多的奇思妙想 关注微信公众号 ...

  6. 利用 Windows 子系统 Linux(WSL)开发 Python 环境搭建

    利用 Windows 子系统 Linux(WSL)开发 Python 一.启用适用于 Linux 的 Windows 子系统 二.安装 Linux 分发版 三.安装并配置 Visual Studio ...

  7. Android资源总结(开发工具/环境搭建/教程/论坛/博客/反编译工具)

    Android资源总结(开发工具/环境搭建/教程/论坛/博客/反编译工具) 在Android发展前景相当好的情况下,本人最近搜集了一些关于Android的相关资源,当然包含以前发布的博客内容,进行了一 ...

  8. linux设备驱动开发之环境搭建(基于exynos4412)

    第一章 linux设备驱动开发之环境搭建(基于exynos4412) 目录 第一章 linux设备驱动开发之环境搭建(基于exynos4412) 1.搭建开发板运行环境 1.1.交叉开发模式 安装交叉 ...

  9. 【 RA4M2开发板环境搭建之串口下载1】

    [ RA4M2开发板环境搭建1] 1. 前言 1.1 活动来源 1.2 开发环境 1.3 RA4M2开发板 2. MDK环境准备 2.1 keil 5下载安装 2.2 安装RA4M2的软件支持包 2. ...

最新文章

  1. 设计模式----单件模式(c++)
  2. 树莓派开发6-配置树莓派的Linux内核
  3. 四十一、文件的物理结构(上)
  4. jvm性能调优 - 11J线上VM调优案例分享
  5. 【网络安全】JAVA代码审计—— XXE外部实体注入
  6. java静态变量实例变量_java中静态变量和实例变量的区别
  7. Oracle分区查询
  8. 【案例分享】KTV网络机顶盒
  9. 【谷月老师讲WPS】用 Windows 11 的 WSL 安装 WPS for Linux
  10. asp.net开源资料——国内.NET论坛源代码
  11. android 手机内存清理,教你彻底清理手机内存的最佳方法,只需一招
  12. Photoshop CC 2018 安装包安装教程
  13. 夏商周秦西东汉 三国两晋南北朝 隋唐五代和十国 辽宋夏金元明清
  14. 百度广告屏蔽及游戏推广屏蔽
  15. 屏幕适配入门-了解基本概念-图片适配
  16. H.265的各种帧(详解):接入图像
  17. excel 区间人数柱状图_『excle 图表 区间计数』excel如何把学生成绩区间分布统计为柱状图...
  18. python编程代码-python编程代码
  19. 我的物联网项目之摇摇车三种消费模式和城市合伙人
  20. 华三HCL和华为ensp不能同时安装且ensp设备启动失败错误代码40怎么办?

热门文章

  1. Java Web 实现 QQ第三方登录
  2. 前端项目中怎么添加依赖
  3. <<R语言入门与实践>>读书笔记
  4. MATLAB 求解特征方程的根轨迹图稳定性分析
  5. uniapp动态显隐导航栏图标
  6. 重庆交通大学c语言上机试题,2021考研复试重庆交通大学《C语言程序设计》复试大纲...
  7. 生物神经元的工作原理对深度学习神经元的启发
  8. ZStack深度试用:部署、架构与网络及其与OpenStack的对比
  9. 基于RSA的t-out-of-n OT协议
  10. nodejs使用redis.js并进行封装,实现数据存取