setCompoundDrawablePadding位置问题

本文详细介绍了如何在Android中自定义CompoundDrawables的间距,包括图片与文字之间的间距和图片左右间距的有效调整。
部署运行你感兴趣的模型镜像
Drawable drawable = context.getResources().getDrawable(R.drawable.icon_mian);
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
groupViewHolder.deliverTip.setCompoundDrawablePadding(26);
groupViewHolder.deliverTip.setCompoundDrawables(drawable, null, null, null);

这样写是只有图片和文字之间的间距

Drawable drawable = context.getResources().getDrawable(R.drawable.icon_mian);
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
groupViewHolder.deliverTip.setCompoundDrawables(drawable, null, null, null);
groupViewHolder.deliverTip.setCompoundDrawablePadding(26);

这样写图片左右间距都有效果

转载于:https://my.oschina.net/u/1028833/blog/492500

您可能感兴趣的与本文相关的镜像

GPT-SoVITS

GPT-SoVITS

AI应用

GPT-SoVITS 是一个开源的文本到语音(TTS)和语音转换模型,它结合了 GPT 的生成能力和 SoVITS 的语音转换技术。该项目以其强大的声音克隆能力而闻名,仅需少量语音样本(如5秒)即可实现高质量的即时语音合成,也可通过更长的音频(如1分钟)进行微调以获得更逼真的效果

package com.example.suyzeko.fragment; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.viewpager2.widget.ViewPager2; import android.os.Handler; import android.os.IBinder; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.Button; import android.widget.ImageButton; import android.widget.PopupWindow; import android.widget.TextView; import android.widget.Toast; import com.example.suyzeko.MainActivity; import com.example.suyzeko.activitys.ledPanel.sixRoads.DeviceDetailsActivity; import com.example.suyzeko.activitys.ledPanel.twoRoads.PhototherapyBoardTwoActivity; import com.example.suyzeko.R; import com.example.suyzeko.SelectDeviceActivity; import com.example.suyzeko.activitys.therapyHelmet.fourZones.TherapyHelmetFourActivity; import com.example.suyzeko.activitys.therapyHelmet.nineteenZones.TherapyHelmetNineteenActivity; import com.example.suyzeko.entity.Device; import com.example.suyzeko.entity.DeviceClass; import com.example.suyzeko.service.BluetoothService; import com.example.suyzeko.utils.BannerAdapter; import com.example.suyzeko.utils.DeviceUtils; import com.example.suyzeko.utils.RetrofitAPI; import com.example.suyzeko.utils.RetrofitClient; import com.google.android.flexbox.FlexboxLayout; import java.util.Arrays; import java.util.List; import java.util.Objects; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class DashboardFragment extends Fragment{ private ViewPager2 viewPager; private FlexboxLayout flexboxContainer; private int buttonCount = 0; private View maskView; // 遮罩层视图 private PopupWindow popupWindow; private final Handler autoScrollHandler = new Handler(); private ImageButton btnAdd; private TextView textView; private BluetoothService bluetoothService; // 蓝牙后台服务实例 private final Runnable autoScrollRunnable = new Runnable() { @Override public void run() { if (viewPager != null) { int currentItem = viewPager.getCurrentItem(); viewPager.setCurrentItem(currentItem + 1, true); autoScrollHandler.postDelayed(this, 3000); // 3秒切换一次 } } }; private boolean isBound = false; private float flexBasisPercent = 0.4f; private int buttonHeight = 90; /** * 服务连接回调 */ private final ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { try { BluetoothService.LocalBinder binder = (BluetoothService.LocalBinder) service; bluetoothService = binder.getService(); isBound = true; registerReceivers(); // 注册广播接收器 } catch (SecurityException e) { throw new RuntimeException(e); } } @Override public void onServiceDisconnected(ComponentName name) { isBound = false; } }; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_dashboard, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (DeviceUtils.isTablet(requireActivity())) { flexBasisPercent = 0.22f; buttonHeight = 110; } else { // 手机设备 } viewPager = view.findViewById(R.id.viewPager); textView = view.findViewById(R.id.device_num); // 示例图片列表 List<Integer> images = Arrays.asList( R.drawable.ontc, R.drawable.offtc ); // 绑定服务 if (bluetoothService != null){ Intent intentBlue = new Intent(getActivity(), BluetoothService.class); bluetoothService.bindService(intentBlue, connection, Context.BIND_AUTO_CREATE); } // 初始化适配器并绑定 BannerAdapter adapter = new BannerAdapter(images); viewPager.setAdapter(adapter); // 设置初始位置(从中间开始,支持向左滑动) viewPager.setCurrentItem(Integer.MAX_VALUE / 2, false); // 自动轮播 autoScrollHandler.postDelayed(autoScrollRunnable, 3000); // 页面切换监听(可选) viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { // 可以在此处理指示器逻辑 } }); flexboxContainer = view.findViewById(R.id.flexbox_container); // 初始化检查:如果没有按钮,显示添加按钮 checkAndShowAddButton(); // 获取加号按钮 btnAdd = view.findViewById(R.id.add_image_button); // 设置点击事件 btnAdd.setOnClickListener(this::showPopupMenu); } @Override public void onAttach(@NonNull Context context) { super.onAttach(context); if (context instanceof OnJumpToActivityListener) { onJumpToActivityListener = (OnJumpToActivityListener) context; } else { throw new RuntimeException("宿主 Activity 需实现 OnJumpToActivityListener"); } } @Override public void onResume(){ super.onResume(); loadActivity(); updateConnectionStatus(); } @Override public void onDestroyView() { super.onDestroyView(); autoScrollHandler.removeCallbacks(autoScrollRunnable); // 防止内存泄漏 // 确保 Fragment 销毁时移除遮罩 removeMask(); super.onDestroy(); } /** * 显示/隐藏"添加按钮"的逻辑 */ private void checkAndShowAddButton() { if (buttonCount == 0) { // 创建"添加按钮" Button addButton = new Button(requireContext()); addButton.setTextColor(Color.parseColor("#2A2A2A")); addButton.setBackgroundResource(R.drawable.button_style); // 可自定义样式 addButton.setText(getString(R.string.add)); // 布局参数 FlexboxLayout.LayoutParams params = new FlexboxLayout.LayoutParams( FlexboxLayout.LayoutParams.WRAP_CONTENT, FlexboxLayout.LayoutParams.WRAP_CONTENT ); params.setFlexBasisPercent(flexBasisPercent); params.setHeight(dpToPx(buttonHeight)); params.setMargins(32, 16, 32, 16); // 点击事件:开始添加普通按钮 addButton.setOnClickListener(v -> { onJumpToActivityListener.jumpToActivityAndClose();// 跳转到搜索设备页面 // navigateToNewActivity(); }); buttonCount++; flexboxContainer.addView(addButton, params); } } private List<Device> deviceLists; /** * 添加动态按钮的方法 * @param deviceList */ public void addNewButton(List<Device> deviceList) { for (Device device:deviceList){ int flag = 0; if(deviceLists != null){ for (Device device1:deviceLists){ if (device1.getDeviceMac().equals(device.getDeviceMac())) { flag = 1; break; } } } if (flag == 1){ continue; } buttonCount++; DeviceClass deviceTypeResources = getDeviceTypeResources(device.getDeviceClassCode()); Button newButton = new Button(requireContext()); newButton.setTag(device); newButton.post(() -> { // 获取按钮实际宽高(单位:像素) int buttonWidth = newButton.getWidth(); int buttonHeight = newButton.getHeight(); // 动态计算文字大小(示例:按钮宽度的 1/6) float textSizePx = buttonWidth / 20f; // 转换为 sp 单位(更符合用户习惯) float textSizeSp = pxToSp(textSizePx); // 设置文字大小 newButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSizeSp); }); // 创建状态图标层叠Drawable Drawable statusIcon = createStatusIcon(device); newButton.setText(device.getDeviceName()); // 获取设备类型对应的图标资源 Drawable icon = ContextCompat.getDrawable(requireContext(), deviceTypeResources.getIconRes()); // 计算按钮实际高度(从布局参数获取) int buttonHeightPx = dpToPx(buttonHeight); // 需与布局中params.setHeight(dpToPx(90))一致 // 设置图标尺寸为按钮高度的60%(按需调整比例) int iconSize = (int) (buttonHeightPx * 0.6); if (icon != null) { // 保持图标宽高比 float aspectRatio = (float) icon.getIntrinsicWidth() / icon.getIntrinsicHeight(); int scaledWidth = (int) (iconSize * aspectRatio); icon.setBounds(0, 0, scaledWidth, iconSize); // 设置绘制区域 } // 设置图标到按钮左侧 newButton.setCompoundDrawables(statusIcon, icon, null, null); newButton.setCompoundDrawablePadding(8); newButton.setBackgroundResource(R.drawable.button_style); newButton.setTextColor(Color.parseColor("#2A2A2A")); // 布局参数(与之前相同) FlexboxLayout.LayoutParams params = new FlexboxLayout.LayoutParams( FlexboxLayout.LayoutParams.WRAP_CONTENT, FlexboxLayout.LayoutParams.WRAP_CONTENT ); params.setFlexBasisPercent(flexBasisPercent); params.setHeight(dpToPx(buttonHeight)); params.setMargins(32, 16, 32, 16); // 点击事件 newButton.setOnClickListener(v -> { if (bluetoothService != null && bluetoothService.getConnectedDevice() != null){ if(device.getDeviceMac().equals(bluetoothService.getMACAddress())){ navigateToNewDeviceDetailsActivity(device); }else { new AlertDialog.Builder(getContext()) .setTitle("Device not connected") .setMessage("Do you want to redirect to the device connection page") // 确认按钮 .setPositiveButton(getString(R.string.OK), (dialog, which) -> { onJumpToActivityListener.jumpToActivityAndClose(); // 跳转到搜索设备页面 }) // 取消按钮 .setNegativeButton(getString(R.string.Cancel), (dialog, which) -> { dialog.dismiss(); }) .show(); } }else { new AlertDialog.Builder(getContext()) .setTitle("Device not connected") .setMessage("Do you want to redirect to the device connection page") // 确认按钮 .setPositiveButton(getString(R.string.OK), (dialog, which) -> { onJumpToActivityListener.jumpToActivityAndClose(); // 跳转到搜索设备页面 }) // 取消按钮 .setNegativeButton(getString(R.string.Cancel), (dialog, which) -> { dialog.dismiss(); }) .show(); } }); // // 长按删除(增加删除后的检查) // newButton.setOnLongClickListener(v -> { // flexboxContainer.removeView(v); // buttonCount--; // checkAndShowAddButton(); // 删除后检查是否需要恢复"添加按钮" // return true; // }); // 将新按钮添加到第一个 flexboxContainer.addView(newButton, 0, params); // --- 关键修改:强制刷新父容器和滚动视图 --- flexboxContainer.post(new Runnable() { @Override public void run() { flexboxContainer.requestLayout(); // 触发 NestedScrollView 重新计算滚动范围 ViewParent parent = flexboxContainer.getParent(); if (parent instanceof ViewGroup) { ((ViewGroup) parent).requestLayout(); } } }); } textView.setText(String.valueOf(buttonCount-1)); } public void updateConnectionStatus() { for (int i = 0; i < flexboxContainer.getChildCount() - 1; i++) { View view = flexboxContainer.getChildAt(i); if (view instanceof Button) { Button btn = (Button) view; Device device = (Device) btn.getTag(); Drawable newStatus = createStatusIcon(device); DeviceClass deviceTypeResources = getDeviceTypeResources(device.getDeviceClassCode()); // 获取设备类型对应的图标资源 Drawable icon = ContextCompat.getDrawable(requireContext(), deviceTypeResources.getIconRes()); // 计算按钮实际高度(从布局参数获取) int buttonHeightPx = dpToPx(buttonHeight); // 设置图标尺寸为按钮高度的60%(按需调整比例) int iconSize = (int) (buttonHeightPx * 0.6); if (icon != null) { // 保持图标宽高比 float aspectRatio = (float) icon.getIntrinsicWidth() / icon.getIntrinsicHeight(); int scaledWidth = (int) (iconSize * aspectRatio); icon.setBounds(0, 0, scaledWidth, iconSize); // 设置绘制区域 } // 设置图标到按钮左侧 btn.setCompoundDrawables(newStatus, icon, null, null); btn.postInvalidate(); // 线程安全刷新 } } } public void updateUnConnectionStatus() { for (int i = 0; i < flexboxContainer.getChildCount() - 1; i++) { View view = flexboxContainer.getChildAt(i); if (view instanceof Button) { Button btn = (Button) view; Device device = (Device) btn.getTag(); if(bluetoothService!= null && device.getDeviceMac().equals(bluetoothService.getMACAddress())){ bluetoothService.disconnect(); Drawable newStatus = createStatusIcon(device); DeviceClass deviceTypeResources = getDeviceTypeResources(device.getDeviceClassCode()); // 获取设备类型对应的图标资源 Drawable icon = ContextCompat.getDrawable(requireContext(), deviceTypeResources.getIconRes()); // 计算按钮实际高度(从布局参数获取) int buttonHeightPx = dpToPx(buttonHeight); // 设置图标尺寸为按钮高度的60%(按需调整比例) int iconSize = (int) (buttonHeightPx * 0.6); if (icon != null) { // 保持图标宽高比 float aspectRatio = (float) icon.getIntrinsicWidth() / icon.getIntrinsicHeight(); int scaledWidth = (int) (iconSize * aspectRatio); icon.setBounds(0, 0, scaledWidth, iconSize); // 设置绘制区域 } // 设置图标到按钮左侧 btn.setCompoundDrawables(newStatus, icon, null, null); btn.postInvalidate(); // 线程安全刷新 } } } } private Drawable createStatusIcon(Device device) { // 获取状态图标资源 int statusRes = isDeviceConnected(device) ? R.drawable.ic_connected_green_round : R.drawable.ic_disconnected_hui_round; // 创建缩放后的状态图标 Drawable statusIcon = ContextCompat.getDrawable(requireContext(), statusRes); int statusSize = dpToPx(12); // 状态图标尺寸 if (statusIcon != null) { statusIcon.setBounds(0, 0, statusSize, statusSize); } return statusIcon; } private boolean isDeviceConnected(Device device) { return bluetoothService != null && bluetoothService.getConnectedDevice() != null && device.getDeviceMac().equals(bluetoothService.getMACAddress()); } /** * 定义类型映射关系 * @param * @return */ private DeviceClass getDeviceTypeResources(String deviceClassCode) { DeviceClass deviceClass; if(deviceClassCode.equals("5A A5 01 01")){ deviceClass = new DeviceClass(0,R.drawable.up_down_black, "ELEVATING WHIRLING LED PANEL"); }else if(deviceClassCode.equals("5A A5 02 02")){ deviceClass = new DeviceClass(1,R.drawable.ontc, "红光床"); }else { deviceClass = new DeviceClass(2,R.drawable.up_down_black, "ELEVATING WHIRLING LED PANEL"); } return deviceClass; } /** * 弹出菜单 * @param anchorView */ public void showPopupMenu(View anchorView) { // 初始化布局 View popupView = LayoutInflater.from(requireContext()).inflate(R.layout.menu_popup_layout, null); // 创建 PopupWindow popupWindow = new PopupWindow( popupView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true ); // 设置背景和动画 popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); popupWindow.setElevation(8); // 阴影效果 popupWindow.setAnimationStyle(R.style.PopupAnimation); // 自定义动画 // 处理菜单项点击 popupView.findViewById(R.id.menu_item_add).setOnClickListener(v -> { // 处理“添加设备”逻辑 popupWindow.dismiss(); navigateToNewActivity(); }); popupView.findViewById(R.id.menu_item_scan).setOnClickListener(v -> { // 处理“扫一扫”逻辑 popupWindow.dismiss(); }); // 添加遮罩层 addMask(); // 设置 PopupWindow 关闭时移除遮罩 popupWindow.setOnDismissListener(() -> removeMask()); // 显示菜单(相对于锚点视图) popupWindow.showAsDropDown(anchorView, dpToPx(-130), dpToPx(15), Gravity.END); } /** * 将遮罩层添加到 Activity 的根布局 */ private void addMask() { if (getActivity() == null) return; ViewGroup rootView = (ViewGroup) getActivity().getWindow().getDecorView(); maskView = LayoutInflater.from(getContext()).inflate(R.layout.layout_background_mask, null); rootView.addView(maskView); } /** * 移除遮罩层 */ private void removeMask() { if (getActivity() == null || maskView == null) return; ViewGroup rootView = (ViewGroup) getActivity().getWindow().getDecorView(); rootView.removeView(maskView); maskView = null; } /** * 跳转查找设备Activity */ private void navigateToNewActivity() { if (getActivity() == null) return; // 避免 Fragment 未附加到 Activity 时崩溃 Intent intent = new Intent(getActivity(), SelectDeviceActivity.class); startActivity(intent); } /** * 跳转到新 Activity * @param device */ private void navigateToNewDeviceDetailsActivity(Device device) { if (getActivity() == null) return; // 避免 Fragment 未附加到 Activity 时崩溃 if(device.getDeviceClassCode().equals("5A A5 01 02")){ Intent intent = new Intent(getActivity(), PhototherapyBoardTwoActivity.class); intent.putExtra("devices",device); startActivity(intent); }else if(device.getDeviceClassCode().equals("5A A5 01 01")){ Intent intent = new Intent(getActivity(), DeviceDetailsActivity.class); intent.putExtra("devices",device); startActivity(intent); }else if(device.getDeviceClassCode().equals("5A A5 02 01")){ Intent intent = new Intent(getActivity(), TherapyHelmetFourActivity.class); intent.putExtra("devices",device); startActivity(intent); }else if(device.getDeviceClassCode().equals("5A A5 02 05")){ Intent intent = new Intent(getActivity(), TherapyHelmetNineteenActivity.class); intent.putExtra("devices",device); startActivity(intent); } } /** * 像素转 sp * @param px * @return */ private float pxToSp(float px) { return px / getResources().getDisplayMetrics().scaledDensity; } /** * dp 转像素工具方法 */ private int dpToPx(int dp) { float density = getResources().getDisplayMetrics().density; return Math.round(dp * density); } /** * 获取用户设备列表 */ private void loadActivity() { // 创建Retrofit服务实例 RetrofitAPI api = RetrofitClient.getClient(getActivity()).create(RetrofitAPI.class); // 发起异步请求 api.deviceFindAll().enqueue(new Callback<List<Device>>() { @Override public void onResponse(Call<List<Device>> call, Response<List<Device>> response) { if (response.isSuccessful() && response.body() != null) { addNewButton(response.body()); deviceLists = response.body(); } } @Override public void onFailure(Call<List<Device>> call, Throwable t) { if (getActivity() != null) { Toast.makeText(getContext(), "网络错误: " + t.getMessage(), Toast.LENGTH_SHORT).show(); // // todo 离线 // DevicesRepository devicesRepository = new DevicesRepository(getActivity()); // List<Devices> deviceByUsername = devicesRepository.getDevicesByUserId(1L); // List<Device> list = new ArrayList<>(); // for (Devices devices:deviceByUsername){ // Device device = new Device(); // device.setDeviceMac(devices.getDeviceMac()); // device.setDeviceName(devices.getDeviceName()); // device.setDeviceClassCode(String.valueOf(devices.getDeviceClassId())); // device.setUserId(devices.getUserId()); // list.add(device); // } // addNewButton(list); // deviceLists = list; // // / } } }); } /** * 注册本地广播接收器 * 用于接收来自BluetoothService的事件 */ private void registerReceivers() { IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothService.ACTION_CONNECTION_STATUS); // 连接状态变化 LocalBroadcastManager.getInstance(getActivity()) .registerReceiver(btReceiver, filter); // 注册广播接收器 } /** * 蓝牙事件广播接收器 * 处理三种事件: * 1. 发现新设备 - 更新设备列表 * 2. 连接状态变化 - 更新UI状态 * 3. 接收到数据 - 显示在消息框 */ private final BroadcastReceiver btReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try { String action = intent.getAction(); if (BluetoothService.ACTION_CONNECTION_STATUS.equals(action)) { // 更新连接状态显示 String status = intent.getStringExtra(BluetoothService.EXTRA_STATUS); if(status.equals("DISCONNECTED")){ updateUnConnectionStatus(); } } } catch (SecurityException e) { throw new RuntimeException(e); } } }; @Override public void onStart() { super.onStart(); Intent intent = new Intent(getActivity(), BluetoothService.class); getActivity().bindService(intent, connection, Context.BIND_AUTO_CREATE); // 绑定服务 } @Override public void onStop() { super.onStop(); if (isBound) { getActivity().unbindService(connection); // 解绑服务‌ isBound = false; } LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(btReceiver); } private OnJumpToActivityListener onJumpToActivityListener; // 在 Fragment 中定义接口 public interface OnJumpToActivityListener { void jumpToActivityAndClose(); } }但设备按钮为4个时 手机版本显示顺序没问题 但平板版本的+add按钮会在第六个按钮的位置 而不是第五个
07-15
public class ShapeDrawableTextView extends AppCompatTextView { // 背景相关 private GradientDrawable gd; private int solidColor = 0; private int strokeColor = 0; private int solidTouchColor = 0; private int strokeTouchColor = 0; private int strokeWith = 0; private int shapeType = 0; private int textTouchColor = 0; private int textColor = 0; private float dashGap = 0; private float dashWidth = 0; // 图标相关 private Drawable[] normalDrawables = new Drawable[4]; // left, top, right, bottom private Drawable[] pressedDrawables = new Drawable[4]; private int drawableWidth = -1; private int drawableHeight = -1; private Rect[] drawableBounds = new Rect[4]; //增加 drawablePadding 的字段 private int compoundDrawablePadding; private boolean customDrawableEnabled = true; private boolean isPressedState = false; public ShapeDrawableTextView(Context context) { super(context); init(context, null); } public ShapeDrawableTextView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context, attrs); } public ShapeDrawableTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { // 初始化背景 gd = new GradientDrawable(); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ShapeTextView); // 背景属性 solidColor = ta.getInteger(R.styleable.ShapeTextView_solidColor, 0x00000000); strokeColor = ta.getInteger(R.styleable.ShapeTextView_strokeColor, 0x00000000); solidTouchColor = ta.getInteger(R.styleable.ShapeTextView_solidTouchColor, 0x00000000); strokeTouchColor = ta.getInteger(R.styleable.ShapeTextView_strokeTouchColor, 0x00000000); textTouchColor = ta.getInteger(R.styleable.ShapeTextView_textTouchColor, 0x00000000); textColor = getCurrentTextColor(); strokeWith = (int) ta.getDimension(R.styleable.ShapeTextView_strokeWith, 0); float radius = ta.getDimension(R.styleable.ShapeTextView_radius, 0); float topLeftRadius = ta.getDimension(R.styleable.ShapeTextView_topLeftRadius, 0); float topRightRadius = ta.getDimension(R.styleable.ShapeTextView_topRightRadius, 0); float bottomLeftRadius = ta.getDimension(R.styleable.ShapeTextView_bottomLeftRadius, 0); float bottomRightRadius = ta.getDimension(R.styleable.ShapeTextView_bottomRightRadius, 0); dashGap = ta.getDimension(R.styleable.ShapeTextView_dashGap, 0); dashWidth = ta.getDimension(R.styleable.ShapeTextView_dashWidth, 0); shapeType = ta.getInt(R.styleable.ShapeTextView_shapeType, GradientDrawable.RECTANGLE); // 图标属性 normalDrawables[0] = ta.getDrawable(R.styleable.ShapeTextView_drawableLeft); normalDrawables[1] = ta.getDrawable(R.styleable.ShapeTextView_drawableTop); normalDrawables[2] = ta.getDrawable(R.styleable.ShapeTextView_drawableRight); normalDrawables[3] = ta.getDrawable(R.styleable.ShapeTextView_drawableBottom); pressedDrawables[0] = ta.getDrawable(R.styleable.ShapeTextView_drawableLeftPressed); pressedDrawables[1] = ta.getDrawable(R.styleable.ShapeTextView_drawableTopPressed); pressedDrawables[2] = ta.getDrawable(R.styleable.ShapeTextView_drawableRightPressed); pressedDrawables[3] = ta.getDrawable(R.styleable.ShapeTextView_drawableBottomPressed); compoundDrawablePadding = ta.getDimensionPixelSize(R.styleable.ShapeTextView_drawablePadding, 0); drawableWidth = ta.getDimensionPixelSize(R.styleable.ShapeTextView_drawableWidth, -1); drawableHeight = ta.getDimensionPixelSize(R.styleable.ShapeTextView_drawableHeight, -1); ta.recycle(); // 确保使用正确的 padding if (compoundDrawablePadding != 0) setCompoundDrawablePadding(compoundDrawablePadding); // 配置背景 gd.setShape(shapeType); if (shapeType == GradientDrawable.RECTANGLE) { gd.setShape(GradientDrawable.RECTANGLE); if (radius != 0) { gd.setCornerRadius(radius); } else { //分别表示 左上 右上 右下 左下 gd.setCornerRadii(new float[]{topLeftRadius, topLeftRadius, topRightRadius, topRightRadius, bottomRightRadius, bottomRightRadius, bottomLeftRadius, bottomLeftRadius}); } } drawBackground(false); // 初始化图标边界 for (int i = 0; i < 4; i++) { drawableBounds[i] = new Rect(); } updateDrawableBounds(); } private void updateDrawableBounds() { for (int i = 0; i < 4; i++) { Drawable drawable = getCurrentDrawable(i); if (drawable != null) { int width = drawableWidth > 0 ? drawableWidth : drawable.getIntrinsicWidth(); int height = drawableHeight > 0 ? drawableHeight : drawable.getIntrinsicHeight(); drawable.setBounds(0, 0, width, height); drawableBounds[i].set(0, 0, width, height); } } } private Drawable getCurrentDrawable(int position) { if (isPressedState && pressedDrawables[position] != null) { return pressedDrawables[position]; } return normalDrawables[position]; } private void drawBackground(boolean isTouch) { if (isTouch) { if (solidTouchColor != 0) gd.setColor(solidTouchColor); if (strokeWith != 0 && strokeTouchColor != 0) { if (dashGap != 0) gd.setStroke(strokeWith, strokeTouchColor, dashGap, dashGap); else gd.setStroke(strokeWith, strokeTouchColor); } if (textTouchColor != 0) setTextColor(textTouchColor); } else { if (solidColor != 0) gd.setColor(solidColor); else gd.setColor(Color.TRANSPARENT); if (strokeWith != 0 && strokeColor != 0) { if (dashGap != 0) gd.setStroke(strokeWith, strokeColor, dashGap, dashGap); else gd.setStroke(strokeWith, strokeColor); } else gd.setStroke(0, Color.TRANSPARENT); if (textTouchColor != 0) setTextColor(textColor); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { setBackground(gd); } postInvalidate(); } @Override public boolean onTouchEvent(MotionEvent event) { boolean handled = super.onTouchEvent(event); int action = event.getActionMasked(); boolean wasPressed = isPressedState; if (action == MotionEvent.ACTION_DOWN) { drawBackground(true); isPressedState = true; } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { drawBackground(false); isPressedState = false; } if (wasPressed != isPressedState) { refreshDrawableState(); invalidate(); } return handled; } // 关键修复:重写 drawable 状态更新方法 @Override protected void drawableStateChanged() { super.drawableStateChanged(); if (customDrawableEnabled) { updateDrawableState(); } } private void updateDrawableState() { int[] state = getDrawableState(); boolean pressed = false; for (int s : state) { if (s == android.R.attr.state_pressed) { pressed = true; break; } } updateDrawables(pressed); } private void updateDrawables(boolean pressed) { // 上述优化后的循环代码 Drawable[] results = new Drawable[4]; for (int i = 0; i < 4; i++) { if (normalDrawables[i] != null || pressedDrawables[i] != null) { Drawable current = pressed ? pressedDrawables[i] : normalDrawables[i]; if (current != null) { current.setBounds(drawableBounds[i]); current.setState(getDrawableState()); } results[i] = current; } else { results[i] = getCompoundDrawables()[i]; } } setCompoundDrawables(results[0], results[1], results[2], results[3]); } @Override protected void onDraw(Canvas canvas) { // 关键修复:仅当自定义 drawable 启用时才处理 if (!customDrawableEnabled) { super.onDraw(canvas); return; } // 先绘制背景和文本 super.onDraw(canvas); // 再绘制状态图标 drawStateDrawables(canvas); } private void drawStateDrawables(Canvas canvas) { int saveCount = canvas.save(); try { // 计算文本尺寸 float textWidth = getPaint().measureText(getText().toString()); Paint.FontMetrics fm = getPaint().getFontMetrics(); float textHeight = fm.descent - fm.ascent; // 计算可用空间 int width = getWidth() - getPaddingLeft() - getPaddingRight(); int height = getHeight() - getPaddingTop() - getPaddingBottom(); // 绘制左侧图标 if (getCurrentDrawable(0) != null) { int left = getPaddingLeft(); int top = (int) ((height - drawableBounds[0].height()) / 2f + getPaddingTop()); canvas.translate(left, top); getCurrentDrawable(0).draw(canvas); canvas.restoreToCount(saveCount); saveCount = canvas.save(); } // 绘制顶部图标 if (getCurrentDrawable(1) != null) { int left = (int) ((width - drawableBounds[1].width()) / 2f + getPaddingLeft()); int top = getPaddingTop(); canvas.translate(left, top); getCurrentDrawable(1).draw(canvas); canvas.restoreToCount(saveCount); saveCount = canvas.save(); } // 绘制右侧图标 if (getCurrentDrawable(2) != null) { int left = getWidth() - getPaddingRight() - drawableBounds[2].width(); int top = (int) ((height - drawableBounds[2].height()) / 2f + getPaddingTop()); canvas.translate(left, top); getCurrentDrawable(2).draw(canvas); canvas.restoreToCount(saveCount); saveCount = canvas.save(); } // 绘制底部图标 if (getCurrentDrawable(3) != null) { int left = (int) ((width - drawableBounds[3].width()) / 2f + getPaddingLeft()); int top = getHeight() - getPaddingBottom() - drawableBounds[3].height(); canvas.translate(left, top); getCurrentDrawable(3).draw(canvas); } } finally { canvas.restoreToCount(saveCount); } } // 新增 API:切换自定义 drawable 模式 public void setCustomDrawableEnabled(boolean enabled) { this.customDrawableEnabled = enabled; if (!enabled) { // 恢复系统默认行为 setCompoundDrawables( normalDrawables[0], normalDrawables[1], normalDrawables[2], normalDrawables[3] ); } invalidate(); } // API: 设置左侧图标 public void setDrawableLeft(Drawable normal, Drawable pressed) { normalDrawables[0] = normal; pressedDrawables[0] = pressed; updateDrawableBounds(); invalidate(); } // API: 设置图标尺寸 public void setDrawableSize(int width, int height) { drawableWidth = width; drawableHeight = height; updateDrawableBounds(); invalidate(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); // 释放资源 for (Drawable drawable : normalDrawables) { if (drawable != null) drawable.setCallback(null); } for (Drawable drawable : pressedDrawables) { if (drawable != null) drawable.setCallback(null); } } } 为什么触发点击事件时,“按下”图片文字都变居中 重叠显示,“松开”又恢复正常
最新发布
08-29
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值