欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义View之RadioGroup实现跨多行显示

程序员文章站 2023-10-31 09:04:28
本文实例为大家分享了android radiogroup跨多行显示的具体代码,供大家参考,具体内容如下 此自定义view源于网络,具体出处不详。 import androi...

本文实例为大家分享了android radiogroup跨多行显示的具体代码,供大家参考,具体内容如下

此自定义view源于网络,具体出处不详。

import android.content.context;
import android.content.res.typedarray;
import android.util.attributeset;
import android.view.motionevent;
import android.view.view;
import android.view.viewgroup;
import android.view.accessibility.accessibilityevent;
import android.view.accessibility.accessibilitynodeinfo;
import android.widget.compoundbutton;
import android.widget.linearlayout;
import android.widget.radiobutton;

public class radiogroup extends linearlayout {
 // holds the checked id; the selection is empty by default 
 private int mcheckedid = -1;
 // tracks children radio buttons checked state 
 private compoundbutton.oncheckedchangelistener mchildoncheckedchangelistener;
 // when true, moncheckedchangelistener discards events 
 private boolean mprotectfromcheckedchange = false;
 private oncheckedchangelistener moncheckedchangelistener;
 private passthroughhierarchychangelistener mpassthroughlistener;

 /**
  * {@inheritdoc}
  */
 public radiogroup(context context) {
  super(context);
  setorientation(vertical);
  init();
 }

 /**
  * {@inheritdoc}
  */
 public radiogroup(context context, attributeset attrs) {
  super(context, attrs);
  mcheckedid = view.no_id;

  final int index = vertical;
  setorientation(index);

  init();
 }

 private void init() {
  mchildoncheckedchangelistener = new checkedstatetracker();
  mpassthroughlistener = new passthroughhierarchychangelistener();
  super.setonhierarchychangelistener(mpassthroughlistener);
 }

 /**
  * {@inheritdoc}
  */
 @override
 public void setonhierarchychangelistener(onhierarchychangelistener listener) {
  // the user listener is delegated to our pass-through listener 
  mpassthroughlistener.monhierarchychangelistener = listener;
 }

 /**
  * {@inheritdoc}
  */
 @override
 protected void onfinishinflate() {
  super.onfinishinflate();

  // checks the appropriate radio button as requested in the xml file 
  if (mcheckedid != -1) {
   mprotectfromcheckedchange = true;
   setcheckedstateforview(mcheckedid, true);
   mprotectfromcheckedchange = false;
   setcheckedid(mcheckedid);
  }
 }

 @override
 public void addview(final view child, int index, viewgroup.layoutparams params) {
  if (child instanceof radiobutton) {
   child.setontouchlistener(new ontouchlistener() {

    @override
    public boolean ontouch(view v, motionevent event) {
     ((radiobutton) child).setchecked(true);
     checkradiobutton((radiobutton) child);
     if (moncheckedchangelistener != null) {
      moncheckedchangelistener.oncheckedchanged(radiogroup.this, child.getid());
     }
     return true;
    }
   });
  } else if (child instanceof linearlayout) {
   int childcount = ((linearlayout) child).getchildcount();
   for (int i = 0; i < childcount; i++) {
    view view = ((linearlayout) child).getchildat(i);
    if (view instanceof radiobutton) {
     final radiobutton button = (radiobutton) view;
     button.setontouchlistener(new ontouchlistener() {

      @override
      public boolean ontouch(view v, motionevent event) {
       button.setchecked(true);
       checkradiobutton(button);
       if (moncheckedchangelistener != null) {
        moncheckedchangelistener.oncheckedchanged(radiogroup.this, button.getid());
       }
       return true;
      }
     });
    }
   }
  }
  super.addview(child, index, params);
 }

 private void checkradiobutton(radiobutton radiobutton) {
  view child;
  int radiocount = getchildcount();
  for (int i = 0; i < radiocount; i++) {
   child = getchildat(i);
   if (child instanceof radiobutton) {
    if (child == radiobutton) {
     // do nothing 
    } else {
     ((radiobutton) child).setchecked(false);
    }
   } else if (child instanceof linearlayout) {
    int childcount = ((linearlayout) child).getchildcount();
    for (int j = 0; j < childcount; j++) {
     view view = ((linearlayout) child).getchildat(j);
     if (view instanceof radiobutton) {
      final radiobutton button = (radiobutton) view;
      if (button == radiobutton) {
       // do nothing 
      } else {
       button.setchecked(false);
      }
     }
    }
   }
  }
 }

 /**
  * <p>sets the selection to the radio button whose identifier is passed in
  * parameter. using -1 as the selection identifier clears the selection;
  * such an operation is equivalent to invoking {@link #clearcheck()}.</p>
  *
  * @param id the unique id of the radio button to select in this group
  * @see #getcheckedradiobuttonid()
  * @see #clearcheck()
  */
 public void check(int id) {
  // don't even bother 
  if (id != -1 && (id == mcheckedid)) {
   return;
  }

  if (mcheckedid != -1) {
   setcheckedstateforview(mcheckedid, false);
  }

  if (id != -1) {
   setcheckedstateforview(id, true);
  }

  setcheckedid(id);
 }

 private void setcheckedid(int id) {
  mcheckedid = id;
 }

 private void setcheckedstateforview(int viewid, boolean checked) {
  view checkedview = findviewbyid(viewid);
  if (checkedview != null && checkedview instanceof radiobutton) {
   ((radiobutton) checkedview).setchecked(checked);
  }
 }

 /**
  * <p>returns the identifier of the selected radio button in this group.
  * upon empty selection, the returned value is -1.</p>
  *
  * @return the unique id of the selected radio button in this group
  * @attr ref android.r.styleable#radiogroup_checkedbutton
  * @see #check(int)
  * @see #clearcheck()
  */
 public int getcheckedradiobuttonid() {
  return mcheckedid;
 }

 /**
  * <p>clears the selection. when the selection is cleared, no radio button
  * in this group is selected and {@link #getcheckedradiobuttonid()} returns
  * null.</p>
  *
  * @see #check(int)
  * @see #getcheckedradiobuttonid()
  */
 public void clearcheck() {
  check(-1);
 }

 /**
  * <p>register a callback to be invoked when the checked radio button
  * changes in this group.</p>
  *
  * @param listener the callback to call on checked state change
  */
 public void setoncheckedchangelistener(oncheckedchangelistener listener) {
  moncheckedchangelistener = listener;
 }

 /**
  * {@inheritdoc}
  */
 @override
 public layoutparams generatelayoutparams(attributeset attrs) {
  return new radiogroup.layoutparams(getcontext(), attrs);
 }

 /**
  * {@inheritdoc}
  */
 @override
 protected boolean checklayoutparams(viewgroup.layoutparams p) {
  return p instanceof radiogroup.layoutparams;
 }

 @override
 protected linearlayout.layoutparams generatedefaultlayoutparams() {
  return new layoutparams(layoutparams.wrap_content, layoutparams.wrap_content);
 }

 @override
 public void oninitializeaccessibilityevent(accessibilityevent event) {
  super.oninitializeaccessibilityevent(event);
  event.setclassname(radiogroup.class.getname());
 }

 @override
 public void oninitializeaccessibilitynodeinfo(accessibilitynodeinfo info) {
  super.oninitializeaccessibilitynodeinfo(info);
  info.setclassname(radiogroup.class.getname());
 }

 public static class layoutparams extends linearlayout.layoutparams {
  /**
   * {@inheritdoc}
   */
  public layoutparams(context c, attributeset attrs) {
   super(c, attrs);
  }

  /**
   * {@inheritdoc}
   */
  public layoutparams(int w, int h) {
   super(w, h);
  }

  /**
   * {@inheritdoc}
   */
  public layoutparams(int w, int h, float initweight) {
   super(w, h, initweight);
  }

  /**
   * {@inheritdoc}
   */
  public layoutparams(viewgroup.layoutparams p) {
   super(p);
  }

  /**
   * {@inheritdoc}
   */
  public layoutparams(marginlayoutparams source) {
   super(source);
  }

  /**
   * <p>fixes the child's width to
   * {@link android.view.viewgroup.layoutparams#wrap_content} and the child's
   * height to {@link android.view.viewgroup.layoutparams#wrap_content}
   * when not specified in the xml file.</p>
   *
   * @param a   the styled attributes set
   * @param widthattr the width attribute to fetch
   * @param heightattr the height attribute to fetch
   */
  @override
  protected void setbaseattributes(typedarray a, int widthattr, int heightattr) {
   if (a.hasvalue(widthattr)) {
    width = a.getlayoutdimension(widthattr, "layout_width");
   } else {
    width = wrap_content;
   }

   if (a.hasvalue(heightattr)) {
    height = a.getlayoutdimension(heightattr, "layout_height");
   } else {
    height = wrap_content;
   }
  }
 }

 /**
  * <p>interface definition for a callback to be invoked when the checked
  * radio button changed in this group.</p>
  */
 public interface oncheckedchangelistener {
  /**
   * <p>called when the checked radio button has changed. when the
   * selection is cleared, checkedid is -1.</p>
   *
   * @param group  the group in which the checked radio button has changed
   * @param checkedid the unique identifier of the newly checked radio button
   */
  void oncheckedchanged(radiogroup group, int checkedid);
 }

 private class checkedstatetracker implements compoundbutton.oncheckedchangelistener {
  public void oncheckedchanged(compoundbutton buttonview, boolean ischecked) {
   // prevents from infinite recursion 
   if (mprotectfromcheckedchange) {
    return;
   }

   mprotectfromcheckedchange = true;
   if (mcheckedid != -1) {
    setcheckedstateforview(mcheckedid, false);
   }
   mprotectfromcheckedchange = false;

   int id = buttonview.getid();
   setcheckedid(id);
  }
 }

 /**
  * <p>a pass-through listener acts upon the events and dispatches them
  * to another listener. this allows the table layout to set its own internal
  * hierarchy change listener without preventing the user to setup his.</p>
  */
 private class passthroughhierarchychangelistener implements viewgroup.onhierarchychangelistener {
  private viewgroup.onhierarchychangelistener monhierarchychangelistener;

  /**
   * {@inheritdoc}
   */
  public void onchildviewadded(view parent, view child) {
   if (parent == radiogroup.this && child instanceof radiobutton) {
    int id = child.getid();
    // generates an id if it's missing 
    if (id == view.no_id) {
     id = child.hashcode();
     child.setid(id);
    }
    ((radiobutton) child).setoncheckedchangelistener(mchildoncheckedchangelistener);
   }

   if (monhierarchychangelistener != null) {
    monhierarchychangelistener.onchildviewadded(parent, child);
   }
  }

  /**
   * {@inheritdoc}
   */
  public void onchildviewremoved(view parent, view child) {
   if (parent == radiogroup.this && child instanceof radiobutton) {
    ((radiobutton) child).setoncheckedchangelistener(null);
   }

   if (monhierarchychangelistener != null) {
    monhierarchychangelistener.onchildviewremoved(parent, child);
   }
  }
 }
}

使用:

Android自定义View之RadioGroup实现跨多行显示

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。