0831Android基础自定义Notification+仿QQ聊天界面的小Demo(上)

自定义Notification

  通过RemoteViews新建一个对象传入自定义的布局,将view对象通过notification的setContent。RemoteViews中有很多限制,平常能使用的有TextView和ImageView以及LinearLayout布局。虽然是自定义布局,但是setIcon等还是要设置(不显示)。。。
  实例如下

//自定义布局
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical">
"@+id/iv_remote_left"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@mipmap/ic_launcher"/>
    "0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:padding="10dp"
        android:text="这个算是内容部分"/>
    "@+id/iv_remote_right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"/>


//初始化notification
 mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
 //活动中相关代码
private void definedNotification() {
        RemoteViews rv=new RemoteViews(getPackageName(),R.layout.remote_layout);
        Intent intent=new Intent(getApplicationContext(),MainActivity.class);//设置pendingintent事件
//                设置pendingintent使用方式
        PendingIntent pend=PendingIntent.getActivity(getApplicationContext(), 1, intent, PendingIntent.FLAG_ONE_SHOT);
        Notification notification=new Notification.Builder(MainActivity.this).setSmallIcon(R.mipmap.ic_launcher).setTicker("我是一条消息")
                .setContentTitle("我是一个标题").setContentText("我是一个文本").setContentInfo("我是内容").setContentIntent(pend)
                .setAutoCancel(true).setWhen(System.currentTimeMillis()).setContent(rv).getNotification();//build
        mNotificationManager.notify(1,notification);
    }

0831Android基础自定义Notification+仿QQ聊天界面的小Demo(上)_第1张图片

仿QQ聊天界面的Demo

  最终目标是实现仿QQ聊天界面,然而做了一大半了依旧感觉山寨╮(╯▽╰)╭。
  要求:能发送表情文字。设置俩button分别控制对话在左边还是右边进行。

  使用自定义ListView布局,通过适配器将EditText中获得的输入文本和图片保存到module中,然后ListView中的TextView通过适配器取出数据。通过ImageView将图片传到EditView中,再通过EditView传入TextView中。注意图片文件插入EditView时,通过EditView中个getText方法获得文本,Editable类型,然后Editable接口(继承Spannable接口,Spannable继承Spanned接口)中有insert(int where, CharSequence text)方法,第一个参数是插入的位置,第二个参数是CharSequence(String、Spanned的父类)类型的文本。不用setText是因为这货会覆盖先前的内容,所以用插入。
  从EditView传到TextView时, 通过“Html.toHtml(Spanned text)”将Editable(Spanned的子类)转换为String类型进行传递 ,然后在得到是通过Html.fromHtml()得到(将String转换为Spanned类型)。为什么不直接把message定义为Editable类型?这样传输数据时就不必进行String转换了。到底可以么?涉及到数据库,貌似string类型的信息更适合存在数据库中,待定。
富文本显示

 private Html.ImageGetter mImageGetter;
 mImageGetter=new Html.ImageGetter() {
            @Override
            public Drawable getDrawable(String source) {
                Drawable drawable=getResources().getDrawable(R.mipmap.ic_launcher);
                drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
                return drawable;
            }
        };
  Spanned spanned=Html.fromHtml("",mImageGetter,null);
     mEtText.getText().insert(mEtText.getSelectionStart(),spanned);

渐变色,在drawable中新建xml文件,shape中

gradient  startColor center Color endColor
设置方向,angle="-90"翻转
type linear线性 radial圆形(必须+gradientRadius) sweep扇形
偏移centerX.Y
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android">
"linear"
            android:startColor="#9CDBE8"
            android:centerColor="#FFFAE3"
            android:endColor="#FAF1CA"
             android:angle="270">

0831Android基础自定义Notification+仿QQ聊天界面的小Demo(上)_第2张图片

设置无标题和全屏无标题

无标题

android:theme="@android:style/Theme.NoTitleBar"

无标题 全屏

android:theme="@android:style/Theme.NoTitleBar.Fullscreen"

在这里设置:
这里写图片描述

0831Android基础自定义Notification+仿QQ聊天界面的小Demo(上)_第3张图片

设置ListView背景不可见,屏蔽点击效果,跟随对话框滚动

  • 背景横线不可见: android:divider=”@null”或者setDivider(null);
  • 屏蔽点击效果: android:listSelector=”@android:color/transparent”
  • 滚动: android:transcriptMode=”alwaysScroll”

添加时间

 chatMessage.setTime(System.currentTimeMillis());//设置时间,得到当前时间的毫秒数

//在适配器中将毫秒数格式为“周二 13:44”
 private SimpleDateFormat mSimple;
 //因为每条信息的时间都不一样,所以对象要在构造器中新建,保证每调用一次就刷新一下时间,大写的HH表示24小时制,小写hh表示12小时制
 public ChatAdapter(LayoutInflater mInflater, Html.ImageGetter mImageGetter, List mData) {
        this.mInflater = mInflater;
        this.mImageGetter = mImageGetter;
        this.mData = mData;
        mSimple=new SimpleDateFormat("EE HH:mm");
    }

//在适配器的getView中得到时间并将其格式化
    String time=mSimple.format(new Date(chatMessage.getTime()));
        vh.tv_time.setText(time);

0831Android基础自定义Notification+仿QQ聊天界面的小Demo(上)_第4张图片

关于刷新数据

  notifyDataSetChanged方法通过一个外部的方法控制如果适配器的内容改变时需要强制调用getView来刷新每个Item的内容,可以实现动态的刷新列表的功能。notifyDataSetChanged()方法是通知adapter调用getview来刷新每个Item。
  

自定义背景

  在drawable中新建xml文件
  corner圆角 中还有bottomLeftRadius、bottomRightRadius、topLeftRadius、topRightRadius分别表示四个角,可设置单个角,也可设置多个角
  solid背景,stroke边框(width边框宽度)

"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android">
    "150dp"/>
    "#00ff00">
    "#ff0000"
        android:width="35dp">

0831Android基础自定义Notification+仿QQ聊天界面的小Demo(上)_第5张图片

全部代码

//新建module类
public class ChatMessage  {
    private int userImg;//用户头像
    private Long time;  //消息到达时间
    private String userName; //用户名
    private String userTitle;//用户头衔
    private String userMessage;//信息
    public ChatMessage(){

    }
    public ChatMessage(int userImg, String userTitle, String userMessage, String userName, Long time) {
        this.userImg = userImg;
        this.userTitle = userTitle;
        this.userMessage = userMessage;
        this.userName = userName;
        this.time = time;
    }

    public int getUserImg() {
        return userImg;
    }

    public void setUserImg(int userImg) {
        this.userImg = userImg;
    }

    public String getUserMessage() {
        return userMessage;
    }

    public void setUserMessage(String userMessage) {
        this.userMessage = userMessage;
    }

    public Long getTime() {
        return time;
    }

    public void setTime(Long time) {
        this.time = time;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserTitle() {
        return userTitle;
    }

    public void setUserTitle(String userTitle) {
        this.userTitle = userTitle;
    }
}

//适配器
package com.example.laowang.chat.adapter;

import android.text.Html;
import android.text.Spanned;
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 com.example.laowang.chat.R;
import com.example.laowang.chat.module.ChatMessage;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2015/8/31.
 */
public class ChatAdapter extends BaseAdapter{
    private LayoutInflater mInflater;
    private List mData;
    private Html.ImageGetter mImageGetter;
    private SimpleDateFormat mSimple;

    public ChatAdapter(LayoutInflater mInflater, Html.ImageGetter mImageGetter, List mData) {
        this.mInflater = mInflater;
        this.mImageGetter = mImageGetter;
        this.mData = mData;
        mSimple=new SimpleDateFormat("EE HH:mm");
    }

    @Override
    public int getCount() {
        return mData.size();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHold vh=null;
        if(convertView==null){
            vh=new ViewHold();
            convertView=mInflater.inflate(R.layout.item_message,null);
            vh.iv_userImg= (ImageView) convertView.findViewById(R.id.iv_userimg);
            vh.tv_time= (TextView) convertView.findViewById(R.id.tv_time);
            vh.tv_userMessage= (TextView) convertView.findViewById(R.id.tv_usermessage);
            vh.tv_userName= (TextView) convertView.findViewById(R.id.tv_username);
            vh.tv_userTitle= (TextView) convertView.findViewById(R.id.tv_usertitle);
            convertView.setTag(vh);
        }else{
            vh= (ViewHold) convertView.getTag();
        }
        ChatMessage chatMessage=mData.get(position);
        vh.iv_userImg.setImageResource(chatMessage.getUserImg());
        vh.tv_userName.setText(chatMessage.getUserName());
//        将时间格式化
        String time=mSimple.format(new Date(chatMessage.getTime()));
        vh.tv_time.setText(time);
        vh.tv_userTitle.setText(chatMessage.getUserTitle());
//     将String(其中包含文字信息)类型的图片转化为Spanned类型
        Spanned spanned=Html.fromHtml(chatMessage.getUserMessage(), mImageGetter, null);
//        vh.tv_userMessage.setText(chatMessage.getUserMessage());
        return convertView;
    }
    class ViewHold{
        ImageView iv_userImg;
        TextView tv_userName;
        TextView tv_userTitle;
        TextView tv_time;
        TextView tv_userMessage;
    }
}

//布局
"http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    "match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:background="#01ABEC">
        "wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textColor="#ffffff"
            android:textAppearance="@android:style/TextAppearance.Large"
            android:layout_margin="5dp"
            android:text="虚拟聊天"/>
    
    "@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:divider="@null"
        android:cacheColorHint="#00000000"
        android:listSelector="@android:color/transparent"
        android:transcriptMode="alwaysScroll"
        android:background="@drawable/backgroundcolor">
    
    "match_parent"
        android:layout_height="wrap_content"
        android:gravity="bottom"
        android:background="@drawable/down_linear_color">
        "@+id/img_iocn"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:src="@drawable/eo_press"
            android:layout_margin="5dp"
            />
        

0831Android基础自定义Notification+仿QQ聊天界面的小Demo(上)_第6张图片

//自定义item
"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    "@+id/tv_time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="10dp"
        android:textColor="#000000"
        android:text="星期一 14:26" />

    "match_parent"
        android:layout_height="wrap_content">

        "@+id/iv_userimg"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:src="@mipmap/ic_launcher" />

        "wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            "wrap_content"
                android:layout_height="wrap_content">

                "@+id/tv_usertitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:background="@drawable/user_occupation_background"
                    android:textColor="#ffffff"
                    android:text="管理员" />

                "@+id/tv_username"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#000000"
                    android:text="大表哥" />
            
            "@+id/tv_usermessage"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@mipmap/eng"
                android:paddingLeft="18dp"
                android:layout_marginRight="70dp"
                android:textColor="#000000"
                android:layout_marginTop="10dp"
                android:text="我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息我是一个信息"/>
        
    

0831Android基础自定义Notification+仿QQ聊天界面的小Demo(上)_第7张图片

//活动

package com.example.laowang.chat;

import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;

import com.example.laowang.chat.adapter.ChatAdapter;
import com.example.laowang.chat.module.ChatMessage;

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

public class MainActivity extends Activity implements View.OnClickListener{
    private ImageView mImgIcon;
    private EditText mEtText;
    private Html.ImageGetter mImageGetter;
    private ListView mListView;
    private List mData;
    private ChatAdapter mChatAdapter;
    private Button mLeftButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mImgIcon= (ImageView) findViewById(R.id.img_iocn);
        mEtText= (EditText) findViewById(R.id.et_text);
        mListView= (ListView) findViewById(R.id.listview);
        mLeftButton= (Button) findViewById(R.id.btn_send_left);

        mData=new ArrayList<>();

//      初始化要在适配器初始化之前,不然mImageGetter为空,得不到图片。发送里的刷新只能刷新数据
        mImageGetter=new Html.ImageGetter() {
            @Override
            public Drawable getDrawable(String source) {
                Drawable drawable=getResources().getDrawable(R.mipmap.ic_launcher);
                drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
                return drawable;
            }
        };
        mListView.setClickable(false);
        mChatAdapter=new ChatAdapter(getLayoutInflater(),mImageGetter,mData);
        mListView.setAdapter(mChatAdapter);
        mLeftButton.setOnClickListener(this);
        mImgIcon.setOnClickListener(this);

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.img_iocn:
                Spanned spanned=Html.fromHtml("",mImageGetter,null);
//                插入图片到光标的位置
                mEtText.getText().insert(mEtText.getSelectionStart(),spanned);
                break;
            case R.id.btn_send_left:
                ChatMessage chatMessage=new ChatMessage();
                chatMessage.setTime(System.currentTimeMillis());
                chatMessage.setUserImg(R.mipmap.ic_launcher);
                chatMessage.setUserName("张三");
                chatMessage.setUserTitle("管理员");
//                chatMessage.setUserMessage(mEtText.getText());
                //                将Editable(Spanned的子类)转换为String类型进行传递 “toHtml(Spanned text)”

                chatMessage.setUserMessage(filterHtml(Html.toHtml(mEtText.getText())));
                mData.add(chatMessage);

                mChatAdapter.notifyDataSetChanged();
//                转到当前位置
//                mListView.setSelection(mData.size()-1);
                mEtText.setText("");
                break;
            default:
                break;
        }
    }
//    过滤掉气泡中多余的部分
    public  String filterHtml(String str){
        str = str.replaceAll("<(?!br|img)[^>]+>", "").trim();
        return str;
    }
}

效果
0831Android基础自定义Notification+仿QQ聊天界面的小Demo(上)_第8张图片

你可能感兴趣的:(Android基础UI)