Android 可以正常在XML中预览的TextClock(解决TextClock在Android studio3.5以上版本无法正常预览)
话不多说 先放图 (xml预览截图)不太会录制gif

时间则是在xm预览中的效果,每次打开xml的时候会自动刷新,但是预览界面中xml是不会动的,实际运行起来每秒跳动一次
坑
Android自带的TextClock会导致xml无法正常预览和刷新
具体问题表现在AS 3.5以上的版本中都有卡顿
具体表现你在xml中放一个TextClock就知道了,这里不赘述
寻找原因
查看TextClock以后发现
核心问题是TextClock中存在一个FormatChangeObserver , 继承于ContentObserver
然后在TextClock的onAttachedToWindow方法中调用了以下代码
private void registerObserver() {
if (mRegistered) {
if (mFormatChangeObserver == null) {
mFormatChangeObserver = new FormatChangeObserver(getHandler());
}
final ContentResolver resolver = getContext().getContentResolver();
Uri uri = Settings.System.getUriFor(Settings.System.TIME_12_24);
if (mShowCurrentUserTime) {
resolver.registerContentObserver(uri, true,
mFormatChangeObserver, UserHandle.USER_ALL);
} else {
// UserHandle.myUserId() is needed. This class is supported by the
// remote views mechanism and as a part of that the remote views
// can be inflated by a context for another user without the app
// having interact users permission - just for loading resources.
// For example, when adding widgets from a managed profile to the
// home screen. Therefore, we register the ContentObserver with the user
// the app is running (e.g. the launcher) and not the user of the
// context (e.g. the widget's profile).
resolver.registerContentObserver(uri, true,
mFormatChangeObserver, UserHandle.myUserId());
}
}
}
这个代码中的FormatChangeObserver主要作用是观察手机的时区变化和12/24小时设置的变化
调用位置是
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mRegistered) {
mRegistered = true;
registerReceiver();
registerObserver();
createTime(mTimeZone);
}
}
具体分析原因就是在onAttachedToWindow中调用了 registerObserver();
导致XML实时更新的时候处理不了(具体原因不明)
Google搜索以后发现AS3.5以后的版本都有这样的问题
解决
其实在项目场景中,时钟样式都是固定的.除非是做组件视图
在自己重写了一个TextClock后
1.忽略了对设备设置中的12/24小时制处理
2.忽略了对时区的处理
3.固定了显示时间的格式
代码如下
package com.linkturing.base.widget;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.SystemClock;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.widget.TextClock;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import java.util.Calendar;
/**
* ================================================
* Description:
* <p>
* Created by Alex on 2020/9/1 0001
* <p>
* 页面内容介绍:
* <p>
* ================================================
*/
public class AlexTextClock extends TextClock {
private String timeFormat = "yyyy年MM月dd日 hh:mm:ss EEEE";
private Calendar mTime;
public AlexTextClock Context context) {
super(context);
}
public AlexTextClock Context context, AttributeSet attrs) {
super(context, attrs);
}
public AlexTextClock Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
onTimeChanged();
}
};
private void onTimeChanged() {
mTime.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(timeFormat, mTime));
}
private final Runnable mTicker = new Runnable() {
public void run() {
onTimeChanged();
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);
getHandler().postAtTime(mTicker, next);
}
};
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mTime = Calendar.getInstance();
mTime.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(timeFormat, mTime));
mTicker.run();
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter);
}
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getContext().unregisterReceiver(mIntentReceiver);
}
}
代码很简单,但是可以在xml中正常预览,以及每次打开xml的时候会更新预览时间
没有设置自定义属性,普通属性和TextView写法相同
写死了时间格式,有需要自己改
需要实现更复杂的功能等以后更新吧
话不多说 先放图 (xml预览截图)不太会录制gif

时间则是在xm预览中的效果,每次打开xml的时候会自动刷新,但是预览界面中xml是不会动的,实际运行起来每秒跳动一次
坑
Android自带的TextClock会导致xml无法正常预览和刷新
具体问题表现在AS 3.5以上的版本中都有卡顿
具体表现你在xml中放一个TextClock就知道了,这里不赘述
寻找原因
查看TextClock以后发现
核心问题是TextClock中存在一个FormatChangeObserver , 继承于ContentObserver
然后在TextClock的onAttachedToWindow方法中调用了以下代码
private void registerObserver() {
if (mRegistered) {
if (mFormatChangeObserver == null) {
mFormatChangeObserver = new FormatChangeObserver(getHandler());
}
final ContentResolver resolver = getContext().getContentResolver();
Uri uri = Settings.System.getUriFor(Settings.System.TIME_12_24);
if (mShowCurrentUserTime) {
resolver.registerContentObserver(uri, true,
mFormatChangeObserver, UserHandle.USER_ALL);
} else {
// UserHandle.myUserId() is needed. This class is supported by the
// remote views mechanism and as a part of that the remote views
// can be inflated by a context for another user without the app
// having interact users permission - just for loading resources.
// For example, when adding widgets from a managed profile to the
// home screen. Therefore, we register the ContentObserver with the user
// the app is running (e.g. the launcher) and not the user of the
// context (e.g. the widget's profile).
resolver.registerContentObserver(uri, true,
mFormatChangeObserver, UserHandle.myUserId());
}
}
}
这个代码中的FormatChangeObserver主要作用是观察手机的时区变化和12/24小时设置的变化
调用位置是
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mRegistered) {
mRegistered = true;
registerReceiver();
registerObserver();
createTime(mTimeZone);
}
}
具体分析原因就是在onAttachedToWindow中调用了 registerObserver();
导致XML实时更新的时候处理不了(具体原因不明)
Google搜索以后发现AS3.5以后的版本都有这样的问题
解决
其实在项目场景中,时钟样式都是固定的.除非是做组件视图
在自己重写了一个TextClock后
1.忽略了对设备设置中的12/24小时制处理
2.忽略了对时区的处理
3.固定了显示时间的格式
代码如下
package com.linkturing.base.widget;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.SystemClock;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.widget.TextClock;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import java.util.Calendar;
/**
* ================================================
* Description:
* <p>
* Created by Alex on 2020/9/1 0001
* <p>
* 页面内容介绍:
* <p>
* ================================================
*/
public class AlexTextClock extends TextClock {
private String timeFormat = "yyyy年MM月dd日 hh:mm:ss EEEE";
private Calendar mTime;
public AlexTextClock Context context) {
super(context);
}
public AlexTextClock Context context, AttributeSet attrs) {
super(context, attrs);
}
public AlexTextClock Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
onTimeChanged();
}
};
private void onTimeChanged() {
mTime.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(timeFormat, mTime));
}
private final Runnable mTicker = new Runnable() {
public void run() {
onTimeChanged();
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);
getHandler().postAtTime(mTicker, next);
}
};
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mTime = Calendar.getInstance();
mTime.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(timeFormat, mTime));
mTicker.run();
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter);
}
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getContext().unregisterReceiver(mIntentReceiver);
}
}
代码很简单,但是可以在xml中正常预览,以及每次打开xml的时候会更新预览时间
没有设置自定义属性,普通属性和TextView写法相同
写死了时间格式,有需要自己改
需要实现更复杂的功能等以后更新吧
话不多说 先放图 (xml预览截图)不太会录制gif

时间则是在xm预览中的效果,每次打开xml的时候会自动刷新,但是预览界面中xml是不会动的,实际运行起来每秒跳动一次
坑
Android自带的TextClock会导致xml无法正常预览和刷新
具体问题表现在AS 3.5以上的版本中都有卡顿
具体表现你在xml中放一个TextClock就知道了,这里不赘述
寻找原因
查看TextClock以后发现
核心问题是TextClock中存在一个FormatChangeObserver , 继承于ContentObserver
然后在TextClock的onAttachedToWindow方法中调用了以下代码
private void registerObserver() {
if (mRegistered) {
if (mFormatChangeObserver == null) {
mFormatChangeObserver = new FormatChangeObserver(getHandler());
}
final ContentResolver resolver = getContext().getContentResolver();
Uri uri = Settings.System.getUriFor(Settings.System.TIME_12_24);
if (mShowCurrentUserTime) {
resolver.registerContentObserver(uri, true,
mFormatChangeObserver, UserHandle.USER_ALL);
} else {
// UserHandle.myUserId() is needed. This class is supported by the
// remote views mechanism and as a part of that the remote views
// can be inflated by a context for another user without the app
// having interact users permission - just for loading resources.
// For example, when adding widgets from a managed profile to the
// home screen. Therefore, we register the ContentObserver with the user
// the app is running (e.g. the launcher) and not the user of the
// context (e.g. the widget's profile).
resolver.registerContentObserver(uri, true,
mFormatChangeObserver, UserHandle.myUserId());
}
}
}
这个代码中的FormatChangeObserver主要作用是观察手机的时区变化和12/24小时设置的变化
调用位置是
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mRegistered) {
mRegistered = true;
registerReceiver();
registerObserver();
createTime(mTimeZone);
}
}
具体分析原因就是在onAttachedToWindow中调用了 registerObserver();
导致XML实时更新的时候处理不了(具体原因不明)
Google搜索以后发现AS3.5以后的版本都有这样的问题
解决
其实在项目场景中,时钟样式都是固定的.除非是做组件视图
在自己重写了一个TextClock后
1.忽略了对设备设置中的12/24小时制处理
2.忽略了对时区的处理
3.固定了显示时间的格式
代码如下
package com.linkturing.base.widget;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.SystemClock;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.widget.TextClock;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import java.util.Calendar;
/**
* ================================================
* Description:
* <p>
* Created by Alex on 2020/9/1 0001
* <p>
* 页面内容介绍:
* <p>
* ================================================
*/
public class AlexTextClock extends TextClock {
private String timeFormat = "yyyy年MM月dd日 hh:mm:ss EEEE";
private Calendar mTime;
public AlexTextClock Context context) {
super(context);
}
public AlexTextClock Context context, AttributeSet attrs) {
super(context, attrs);
}
public AlexTextClock Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
onTimeChanged();
}
};
private void onTimeChanged() {
mTime.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(timeFormat, mTime));
}
private final Runnable mTicker = new Runnable() {
public void run() {
onTimeChanged();
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);
getHandler().postAtTime(mTicker, next);
}
};
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mTime = Calendar.getInstance();
mTime.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(timeFormat, mTime));
mTicker.run();
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter);
}
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getContext().unregisterReceiver(mIntentReceiver);
}
}
代码很简单,但是可以在xml中正常预览,以及每次打开xml的时候会更新预览时间
没有设置自定义属性,普通属性和TextView写法相同
写死了时间格式,有需要自己改
需要实现更复杂的功能等以后更新吧