自定义RelativeLayout控件,setVisibility(View.INVISIBLE)竟然无效

在Android项目中自定义了一个RelativeLayout,遇到了onDraw()不执行、ImageView图片重叠以及setVisibility(View.INVISIBLE)无效的问题。通过查阅资料,分别通过setWillNotDraw(false)、只使用setBackgroundDrawable解决前两个问题,而对setVisibility无效的问题,通过clearAnimation()解决,即使动画相关代码已注释。

        在项目中,我自定义了一个RelativeLayout控件,写的也很简单。使用的过程竟然遇到很多问题,让我很惊讶,一下觉得自己对android认识太浅。

        遇到了三个问题:

           1.重载的onDraw()函数不会被执行;

           2.Imageview同时使用了setImageResource和setBackgroundDrawable,图片竟然出现前后图片重叠在一起;

           3.setVisibility(View.INVISIBLE)竟然无效;

 

              由于项目比较紧张,感紧百度一下:

                 问题1:加上这句就可以了setWillNotDraw(false);

                      具体原因可以看这个http://blog.youkuaiyun.com/look85/article/details/8442675

                 问题2:这个问题我也不知到原因,后来我只使用setBackgroundDrawable,问题就解决了。真是奇怪,懂的求教!

                  问题3:这个就纠结了,网上几乎找不到这方面的问题,后来看到一篇文章就说加一句clearAnimation();靠,还真解决了。可是我都把animation有关的代码注释掉了。不懂不懂。


       附上我定义的MyCollectButton代码:

public class MyCollectButton extends RelativeLayout {

    private static final String TAG = "MyCollectButton";
    private Paint mPaint = new Paint();
    private boolean mDrawOutline = false;
    public ImageView imageView;
    private TextView textView;
    private RelativeLayout layout = null;
    private int nBgColor = Color.rgb(73, 85, 104);
        
    public MyCollectButton(Context context) {
        super(context);
        initView(context);
        // TODO Auto-generated constructor stub
    }

    public MyCollectButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        setWillNotDraw(false);

        initView(context);
    }
     public MyCollectButton(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            initView(context);
        }

    @Override  
    protected void onFinishInflate() {  
        super.onFinishInflate();  
       
    }  
    private void initView(Context context){

        if(layout==null){
         LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         layout = (RelativeLayout) inflater.inflate(R.layout.collect_item_layout,this);
        }
        this.setBackgroundColor(nBgColor);
         imageView = (ImageView)layout.findViewById(R.id.collect_app_imageView);
         textView = (TextView)layout.findViewById(R.id.collect_app_title);
         textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,25*Launcher.g_fscale);
         this.setOnFocusChangeListener(new View.OnFocusChangeListener() {

             @Override
             public void onFocusChange(View v, boolean hasFocus) {
                 // TODO Auto-generated method stub
                 if (hasFocus) {

                     mDrawOutline = true;
                     v.bringToFront();
                     curImageView(v);

                     // onCursorFocusOn();
                 } else {
                     lastImageView(v);
                     mDrawOutline = false;
                 }
             }
         });
         mPaint.setColor(Color.WHITE);
         mPaint.setStyle(Paint.Style.FILL);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mDrawOutline) {
            //this.setBackgroundColor(Color.rgb(236, 107, 13));
            final float left = getPaddingLeft();
            final float right = getWidth() - getPaddingRight();
            final float top = getPaddingTop();
            final float bottom = getHeight() - getPaddingBottom();

            canvas.drawRect(left, top, right, top + 1.5f, mPaint);
            canvas.drawRect(left, top, left + 1.5f, bottom, mPaint);
            canvas.drawRect(left, bottom - 1.5f, right, bottom, mPaint);
            canvas.drawRect(right - 1.5f, top, right, bottom, mPaint);
        } else {
            //this.setBackgroundColor(nBgColor);
        }

        super.onDraw(canvas);
    }

    private void curImageView(View paramView) {
        final ScaleAnimation localScaleAnimation = new ScaleAnimation(1.0F, 1.1F,
                1.0F, 1.1F, 1, 0.5F, 1, 0.5F);
        localScaleAnimation.setInterpolator(new AccelerateInterpolator(1.0F));
        localScaleAnimation.setDuration(200L);
        localScaleAnimation.setFillAfter(true);
        localScaleAnimation
                .setAnimationListener(new Animation.AnimationListener() {
                    public void onAnimationEnd(Animation paramAnimation) {
                    }

                    public void onAnimationRepeat(Animation paramAnimation) {
                    }

                    public void onAnimationStart(Animation paramAnimation) {
                    }
                });
        paramView.startAnimation(localScaleAnimation);
    }

    private void lastImageView(View paramView) {
        final ScaleAnimation localScaleAnimation = new ScaleAnimation(1.1F, 1.0F,
                1.1F, 1.0F, 1, 0.5F, 1, 0.5F);
        localScaleAnimation.setInterpolator(new AccelerateInterpolator(1.0F));
        localScaleAnimation.setDuration(200L);
        localScaleAnimation.setFillAfter(true);
        paramView.startAnimation(localScaleAnimation);
    }

    /**
     * 设置图片资源
     */
    public void setIconResource(int resId) {
        imageView.setImageResource(resId);
    }
    
    public void setIconBackgroundDrawable(Drawable drawable) {
        imageView.setBackgroundDrawable(drawable);
    }

    /**
     * 设置显示的文字
     */
    public void setTextViewText(String text) {
        textView.setText(text);
        
        if(text.equals("添加应用")){
            //nBgColor = Color.rgb(138, 138, 138);
            textView.setTextColor(Color.rgb(145, 145, 145));
        }else{
            //nBgColor = Color.rgb(73, 85, 104);
            textView.setTextColor(Color.rgb(255, 255, 255));
        }
        //this.setBackgroundColor(nBgColor);
        
    }
}





package com.weishitechsub.kdcxqwb.fragment.Adapter; import android.Manifest; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.viewholder.BaseViewHolder; import com.weishitechsub.kdcxqwb.R; import com.weishitechsub.kdcxqwb.bean.ListBean; import com.weishitechsub.kdcxqwb.utils.PackageNotificationSender; import com.weishitechsub.kdcxqwb.utils.ReminderManager; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class MyCourierAdapter extends BaseQuickAdapter<ListBean, BaseViewHolder> { private static final String TAG = "MyCourierAdapter"; private List<ListBean> mTrackList; private Context context; // 存储:用户手动开启了提醒的单号 private final Set<String> remindedEnabled = ConcurrentHashMap.newKeySet(); // 存储:每个单号最后一次被提醒到的状态(用于去重) private final Map<String, String> remindedStates = new ConcurrentHashMap<>(); private Handler mainHandler = new Handler(Looper.getMainLooper()); int type; // 缓存当前列表数据,用于根据单号查找最新状态 private List<ListBean> currentList; public MyCourierAdapter(List<ListBean> list, Context context, int type) { super(R.layout.my_courier_adapter, list); this.context = context; this.type = type; ReminderManager.getInstance(context); // 初始化单例 } @Override protected void convert(@NonNull BaseViewHolder baseViewHolder, ListBean dataBean) { String number = dataBean.getNum(); baseViewHolder.setText(R.id.tv_number, number); baseViewHolder.setText(R.id.tv_address, dataBean.getContext()); if (type == 1) { baseViewHolder.getView(R.id.tv_remind).setVisibility(View.GONE); baseViewHolder.getView(R.id.iv_remind).setVisibility(View.GONE); } else { baseViewHolder.getView(R.id.tv_remind).setVisibility(View.VISIBLE); baseViewHolder.getView(R.id.iv_remind).setVisibility(View.VISIBLE); } // 设置快递公司信息和图标 if (dataBean.getType() != null) { String trackName = getTrackName(dataBean.getType()); baseViewHolder.setText(R.id.tv_type, trackName); ImageView logo = baseViewHolder.getView(R.id.iv_logo); LinearLayout line = baseViewHolder.getView(R.id.line); setCompanyLogo(trackName, logo, line); } // ===== 获取状态文本 ===== String state = dataBean.getState(); String stateText = getStateText(state); baseViewHolder.setText(R.id.tv_state, stateText != null ? stateText : "未知状态"); ImageView ivRemind = baseViewHolder.getView(R.id.iv_remind); // === 统一处理所有状态分支 === if (state == null || TextUtils.isEmpty(stateText)) { // 情况1:状态无效 ivRemind.setEnabled(false); ivRemind.setAlpha(0.4f); refreshRemindIcon(ivRemind, false); ivRemind.setOnClickListener(v -> { Toast.makeText(context.getApplicationContext(), "该快递状态异常,暂不支持提醒功能", Toast.LENGTH_SHORT).show(); }); } else if (isTerminatedState(state)) { // 情况2:终止状态 → 禁止开启提醒,但允许点击查看提示 ivRemind.setEnabled(true); // ✅ 保持可点击 ivRemind.setAlpha(0.5f); // ✅ 视觉上变灰,表示不可用 refreshRemindIcon(ivRemind, false); // 显示关闭图标 ivRemind.setOnClickListener(v -> { String tip; if (state.startsWith("3")) { tip = getSignReceivedTip(state); } else if (state.startsWith("4")) { tip = "该快递已拒签,订单结束。"; } else if (state.startsWith("6")) { tip = "该快递已被退回。"; } else { tip = "该快递已完成,无需提醒。"; } Toast.makeText(context.getApplicationContext(), tip, Toast.LENGTH_SHORT).show(); }); // 自动取消本地提醒标记 ReminderManager.getInstance(context).disableReminder(number); remindedStates.put(number, state); } // 更新缓存列表 currentList = getData(); } // 检查权限后开启提醒,并发送通知 private void enableReminderWithPermissionCheck(ListBean dataBean) { String number = dataBean.getNum(); String state = dataBean.getState(); String type = dataBean.getType(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { showNotificationPermissionDialog(); return; } } ReminderManager.getInstance(context).enableReminder(number); Toast.makeText(context, "已开启提醒: " + number, Toast.LENGTH_SHORT).show(); String companyName = getTrackName(type); sendStatusNotification(number, companyName, getStateText(state), getNotifyContent(state)); } // 刷新提醒按钮图标 private void refreshRemindIcon(ImageView ivRemind, boolean isEnabled) { if (isEnabled) { ivRemind.setImageResource(R.mipmap.button_on); } else { ivRemind.setImageResource(R.mipmap.button_off); } } // 获取主状态文本(兼容 3xx) private String getStateText(String state) { if (state == null || state.isEmpty()) return null; String mainState = state.substring(0, 1); switch (mainState) { case "0": return "在途"; case "5": return "派件"; case "3": return "签收"; case "6": return "退回"; case "4": return "退签"; case "1": return "揽收"; case "7": return "转投"; case "2": return "疑难"; case "8": return getDetailClearanceText(state); default: return null; } } // 清关详情 private String getDetailClearanceText(String state) { switch (state) { case "8": return "清关"; case "10": return "待清关"; case "11": return "清关中"; case "12": return "已清关"; case "13": return "清关异常"; default: return "清关"; } } // 是否为终止状态(3xx, 4xx, 6xx) private boolean isTerminatedState(String state) { if (state == null || state.isEmpty()) return false; char firstChar = state.charAt(0); return firstChar == '3' || firstChar == '4' || firstChar == '6'; } // 签收子状态提示 private String getSignReceivedTip(String state) { switch (state) { case "301": return "该快递已由本人签收,无需提醒。"; case "302": return "该快递在派件异常后完成签收。"; case "303": return "该快递已被他人代签,请注意查收。"; case "304": return "该快递已投入快递柜或驿站签收。"; default: return "该快递已签收,无需提醒。"; } } // 获取通知内容 private String getNotifyContent(String state) { if (state.startsWith("3")) return getSignReceivedTip(state); switch (state) { case "0": return "您的快递已在运输途中,正在路上~"; case "5": return "快递员正在为您派送,请注意查收!"; case "6": return "很遗憾,您的快递因故被退回。"; case "4": return "您已拒签该快递,订单已完成。"; default: return "快递因地址问题已转投其他网点。"; } } // 发送状态变更通知 private void sendStatusNotification(String number, String company, String titleSuffix, String content) { PackageNotificationSender sender = new PackageNotificationSender(context); int id = ("status_" + number).hashCode() & Integer.MAX_VALUE; id = (id % 1_000_000) + 2000; sender.sendCustomNotification(id, "📌 快递" + titleSuffix, content, number, company); } // 根据 type 查找快递公司名称 private String getTrackName(String type) { if (mTrackList != null) { for (ListBean item : mTrackList) { if (item.getNum() != null && type != null && TextUtils.equals(item.getNum(), type)) { return item.getCom(); } } } return ""; } // 设置外部数据源 public void setTrackList(List<ListBean> list) { this.mTrackList = list; } // 缓存当前列表 @Override public void setNewInstance(List<ListBean> list) { super.setNewInstance(list); this.currentList = list; } // 获取所有开启提醒的条目 public List<ListBean> getRemindedItems() { List<ListBean> result = new ArrayList<>(); if (currentList == null) return result; Set<String> remindedNumbers = ReminderManager.getInstance(context).getRemindedNumbers(); for (ListBean bean : currentList) { if (remindedNumbers.contains(bean.getNum())) { result.add(bean); } } return result; } /** * 根据快递公司名称设置对应的 Logo 图标 */ private void setCompanyLogo(String name, ImageView logo, LinearLayout line) { if (name == null || name.isEmpty()) { logo.setVisibility(View.INVISIBLE); line.setVisibility(View.VISIBLE); return; } switch (name) { case "邮政快递包裹": logo.setImageResource(R.mipmap.img_yz_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "京东物流": logo.setImageResource(R.mipmap.img_jd_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "圆通快递": logo.setImageResource(R.mipmap.img_yt_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "中通快递": logo.setImageResource(R.mipmap.img_zt_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "顺丰速运": logo.setImageResource(R.mipmap.img_sf_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "韵达快递": logo.setImageResource(R.mipmap.img_yd_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "申通快递": logo.setImageResource(R.mipmap.img_st_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; case "EMS": logo.setImageResource(R.mipmap.img_ems_bg); logo.setVisibility(View.VISIBLE); line.setVisibility(View.GONE); break; default: logo.setVisibility(View.GONE); line.setVisibility(View.VISIBLE); break; } } private void showNotificationPermissionDialog() { if (context == null) return; new AlertDialog.Builder(context) .setTitle("需要通知权限") .setMessage("请允许本应用发送快递状态提醒通知。\n\n进入【设置】→【通知】中开启权限。") .setPositiveButton("去开启", (dialog, which) -> { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.fromParts("package", context.getPackageName(), null)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); }) .setNegativeButton("取消", (dialog, which) -> { Toast.makeText(context, "未授予通知权限,无法开启提醒", Toast.LENGTH_SHORT).show(); }) .create() .show(); } } <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:background="@drawable/outcome_bg" android:paddingTop="16dp" android:paddingLeft="@dimen/anythink_14dp" android:paddingRight="@dimen/anythink_14dp" > <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/tv_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="12345678998765" android:textSize="18sp" /> <TextView android:id="@+id/tv_remind" android:layout_width="wrap_content" android:layout_height="25dp" android:text="取件提醒" android:textColor="@color/black" android:textSize="@dimen/sp_14" android:padding="3dp" android:layout_toRightOf="@id/tv_number" android:layout_marginLeft="@dimen/base_dp_8" /> <ImageView android:id="@+id/iv_remind" android:layout_width="40dp" android:layout_height="30dp" android:src="@mipmap/button_off" android:layout_toRightOf="@+id/tv_remind" android:layout_centerVertical="true" /> <TextView android:id="@+id/tv_state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="派件中" android:textSize="14sp" android:textColor="#2281FF" android:layout_alignParentRight="true" /> </RelativeLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:layout_marginBottom="@dimen/dp_10" > <ImageView android:id="@+id/iv_logo" android:layout_width="46dp" android:layout_height="@dimen/dp_40" android:src="@mipmap/img_jd_bg" android:visibility="invisible" /> <LinearLayout android:id="@+id/line" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="@dimen/dp_10" android:background="@drawable/round_corner_line" > <TextView android:id="@+id/tv_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="1111" android:textColor="@color/white" android:layout_gravity="center" /> </LinearLayout> <TextView android:id="@+id/tv_type" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="京东快递" android:textSize="15sp" android:textColor="#333333" android:layout_toRightOf="@id/iv_logo" android:layout_marginLeft="@dimen/anythink_12dp" /> <TextView android:id="@+id/tv_address" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="【合肥市】合肥市庐阳区四里河街道在派件" android:textSize="12sp" android:textColor="#666666" android:layout_toRightOf="@id/iv_logo" android:layout_below="@id/tv_type" android:layout_marginLeft="@dimen/anythink_12dp" android:maxLines="2" android:ellipsize="end" /> </RelativeLayout> </LinearLayout>这段代码没有快递logo显示<LinearLayout android:id="@+id/line" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="@dimen/dp_10" android:background="@drawable/round_corner_line" > <TextView android:id="@+id/tv_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="1111" android:textColor="@color/white" android:layout_gravity="center" /> </LinearLayout>这个,隐藏iv_logo这个控件但是tv_type、tv_address,字体会盖到line这个控件
最新发布
11-29
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值