项目3(通知及坐标的获取)

1 完成效果

在这里插入图片描述

2 布局代码

<?xml version="1.0" encoding="utf-8"?>

<EditText
    android:id="@+id/et_ip"
    android:hint="输入IP地址"
    android:inputType="number"
    android:ems="20"
    android:textSize="20sp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
<TextView
    android:id="@+id/tv_showIP"
    android:textSize="20sp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="192.168.1.1" />
<View
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:background="#66CCFF"/>
<TextView
    android:id="@+id/tv_coordinate"
    android:textSize="20sp"
    android:hint="显示touch坐标"
    android:layout_marginTop="10dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<RelativeLayout
    android:id="@+id/relative_layout"
    android:layout_weight="1"
    android:layout_width="match_parent"
    android:layout_height="0dp">

    <ImageView
        android:id="@+id/img_view"
        android:layout_width="96px"
        android:layout_height="96px"
        android:src="@mipmap/ic_launcher_round" />
</RelativeLayout>
<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <LinearLayout
        android:orientation="horizontal"
        android:gravity="center_horizontal|bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btn_hang"
            android:text="悬挂通知"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btn_normal"
            android:text="普通通知"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/btn_fold"
            android:text="折叠通知"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>

    </LinearLayout>

    <LinearLayout
        android:gravity="center_horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btn_clear"
            android:text="清除通知(不建议使用)"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>

说明:

1 本布局中 把中间显示图片空白区域下压要用到RelativeLayout,并且layout_weight=“1”,且layout_width="match_parent"才能达到效果.
2 底下有两行按钮,分别用两个包裹,第一个设置横向,注意的是layout_weight=“1”,layout_width=“0dp”.这里给它设置的是按钮所占大小权重,3个按钮权重相同,就达到了效果.

3 监听事件

package com.example.myapplication;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RemoteViews;
import android.widget.TextView;

import java.util.Locale;

public class Main6Activity extends AppCompatActivity implements View.OnClickListener {
// 1. 定义这些控件
private EditText etIp;
private TextView tvShowIp;
private TextView tvXY;

private ImageView imgView;
private Rect rect = new Rect();  // 布局的长方形对象
private float deltaX, deltaY;   // x、y方向上的移动偏移量

private Button btnHang, btnNormal, btnFold, btnClear;
private NotificationManager manager;  // 消息管理器对象

@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main6);
    // 2. 获取控件对象,并设置相关的监听事件
    ininView();

    // 3. 设置事件监听器
    // 3.1 图片的移动的Touch事件
    imgView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return moveImage(v, event);
        }
    });

    // 3.2 键盘输入的事件
    etIp.setOnKeyListener(new View.OnKeyListener() {
        // 4. 处理监听事件
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {

            switch (event.getAction()) {
                case KeyEvent.ACTION_UP:
                    String ip = etIp.getText().toString();
                    if (ip.length() == 12) {
                        String newIp = analysisIp(ip);
                        tvShowIp.setText(newIp);

                        // 关闭软键盘
                        closeSoftKeyboard(v);
                    }
                    break;
            }
            return false;
        }
    });

// 4. 创建通知渠道
createChannel();
}

// 功能:初始化布局上的所有组件,并设置监听事件
private void ininView() {
    // 获取ip解析的两个控件
    etIp = findViewById(R.id.et_ip);
    tvShowIp = findViewById(R.id.tv_showIP);
    tvXY = findViewById(R.id.tv_coordinate);

    // 获取ImageView控件
    imgView = findViewById(R.id.img_view);

    // 初始化消息的3个按钮,并设置监听事件
    btnHang = findViewById(R.id.btn_hang);
    btnNormal = findViewById(R.id.btn_normal);
    btnFold = findViewById(R.id.btn_fold);
    btnClear = findViewById(R.id.btn_clear);

    btnHang.setOnClickListener(this);
    btnNormal.setOnClickListener(this);
    btnFold.setOnClickListener(this);
    btnClear.setOnClickListener(this);
}

// 功能:关闭软键盘
private void closeSoftKeyboard(View view) {
    InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
    if (imm != null && imm.isActive()) {
        imm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
    }
}

//  功能:根据输入的ip字符串,解析为ip地址格式
private String analysisIp(String ip) {
    // 转换IP地址
    String newIp = "";
    for (int i = 0; i < ip.length() / 3; i++) {
        newIp += ip.substring(i * 3, Math.min(i * 3 + 3, ip.length())) + ".";
    }
    return newIp.substring(0, newIp.length() - 1);
}

// 功能:根据MotionEvent的触发,计算ImageView的位置,并通过设置ImageView的margin移动图片
private boolean moveImage(View v, MotionEvent event) {
    // 1. 获取触控点的坐标,并显示到TextView
    float x = event.getX() + v.getLeft();
    float y = event.getY() + v.getTop();
    String pos = "触点坐标:" + String.format(Locale.CHINA, "%.2f", x)
            + ", " + String.format(Locale.CHINA, "%.2f", y);
    TextView tvXY = findViewById(R.id.tv_coordinate);

    // 2. 获取可以移动的范围大小
    findViewById(R.id.relative_layout).getDrawingRect(rect);

    // 3. 获取imageView的布局参数
    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();

    // 4. 处理ACTION_DOWN、ACTION_MOVE、ACTION_UP的事件
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            deltaX = x - params.leftMargin;
            deltaY = y - params.topMargin;
            break;
        case MotionEvent.ACTION_MOVE:
            int moveX = Math.round(x - deltaX);
            int moveY = Math.round(y - deltaY);

            if (moveX >= rect.left && moveX <= rect.right
                    && moveY >= rect.top && moveY <= rect.bottom) {
                params.leftMargin = moveX;
                params.topMargin = moveY;
                imgView.setLayoutParams(params);
            }
            break;
        case MotionEvent.ACTION_UP:
            imgView.performClick();
            break;
    }
    return true;
}

// 创建3种不同的消息渠道
private void createChannel() {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        // 悬挂通知:等级最高
        String channelId = "悬挂";
        String channelName = "悬挂通知";
        int importance = NotificationManager.IMPORTANCE_HIGH;  // 消息的重要性等级
        createNotificationChannel(channelId, channelName, importance);

        // 普通通知:等级中等
        channelId = "普通";
        channelName = "普通通知";
        importance = NotificationManager.IMPORTANCE_DEFAULT;
        createNotificationChannel(channelId, channelName, importance);

        // 折叠通知:等级最低
        channelId = "折叠";
        channelName = "折叠通知";
        importance = NotificationManager.IMPORTANCE_LOW;
        createNotificationChannel(channelId, channelName, importance);
    }
}

@RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChannel(String channelId, String channelName, int importance) {
    NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
    manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    manager.createNotificationChannel(channel);
}

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.btn_hang:
            sendHang();
            break;
        case R.id.btn_normal:
            sendNormal();
            break;
        case R.id.btn_fold:
            sendFold();
            break;
        case R.id.btn_clear:
            clearAllNotification();
    }
}

// 发送悬挂消息
private void sendHang() {
    // 设置消息传递的动作,通过PendingIntent进行传递(自定义Intent跳转的第二个Activity需要自行定义)
    Intent intent = new Intent(Main6Activity.this, Main7Activity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(Main6Activity.this, 0, intent, 0);

    // 1. 创建消息构造器,设置相关的属性;通过Builder构造方法传递channelId,匹配createChannel()方法中设置的channelId
    NotificationCompat.Builder builder = new NotificationCompat.Builder(Main6Activity.this, "悬挂");
    builder.setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("悬挂通知")
            .setContentText("今天中午会下大雨")
            .setWhen(System.currentTimeMillis())
            .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true);

    // 针对低于Android 8.0的设置
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        builder.setFullScreenIntent(pendingIntent, true);
    }

    // 2. 通过builder构建消息对象
    Notification notification = builder.build();

    // 3. 通过消息管理器发送消息
    if (manager == null) {
        manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  // 消息通知是系统服务
    }
    manager.notify(1, notification); // 发送消息的id必须唯一,否则会被后面发送的消息覆盖
}

// 发送普通消息
private void sendNormal() {
    // 设置消息传递的动作,通过PendingIntent进行传递(自定义Intent跳转的第二个Activity需要自行定义)
    Intent intent = new Intent(Main6Activity.this, Main7Activity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(Main6Activity.this,
            0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    // 1. 创建消息构造器,设置相关的属性;通过Builder构造方法传递channelId,匹配createChannel()方法中设置的channelId
    NotificationCompat.Builder builder = new NotificationCompat.Builder(Main6Activity.this, "普通");
    builder.setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("普通通知")
            .setContentText("今天中午会下大雨")
            .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true);

// 2. 通过builder构建消息对象
Notification notification = builder.build();

    // 3. 通过消息管理器发送消息
    if (manager == null) {
        manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    }
    manager.notify(2, notification);
}

// 发送:发送折叠消息(了解即可)
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private void sendFold() {
    // 设置消息传递的动作,通过PendingIntent进行传递(自定义Intent跳转的第二个Activity需要自行定义)
    Intent intent = new Intent(Main6Activity.this, Main7Activity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(Main6Activity.this, 0, intent, 0);

    // 1. 创建消息构造器,设置相关的属性;通过Builder构造方法传递channelId,匹配createChannel()方法中设置的channelId
    NotificationCompat.Builder builder = new NotificationCompat.Builder(Main6Activity.this, "折叠");
    builder.setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("折叠通知")
            .setContentText("今天中午会下大雨")
            .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true);

    // 2. 通过builder构建消息对象
    Notification notification = builder.build();

    // 3. 设置折叠通知展开后的布局
    notification.bigContentView = new RemoteViews(getPackageName(), R.layout.activity_main7);

    // 4. 通过消息管理器发送消息
    if (manager == null) {
        manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    }
    manager.notify(3, notification);
}

// 功能:清除所有的通知,一般不使用
private void clearAllNotification() {
    manager.cancelAll();

    // 清除某一个通知方法:manager.cancel(id),此处的id是notify()的id
}

// 功能:activity界面上的触控事件处理
@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        float x = event.getX();
        float y = event.getY();
        String pos = "触点坐标:" + String.format(Locale.CHINA, "%.2f", x)
                + ", " + String.format(Locale.CHINA, "%.2f", y);
        tvXY.setText(pos);

// Toast.makeText(this, pos, Toast.LENGTH_LONG).show();
}
return super.onTouchEvent(event);
}
}

发布了11 篇原创文章 · 获赞 8 · 访问量 917

猜你喜欢

转载自blog.csdn.net/qq_44739668/article/details/89317516