1

我正在使用此approach。我做了所有的步驟中顯示的自定義開關在Android 2.3或以上顯示。但是當我運行該應用程序拋出一個錯誤,我在下面顯示。我也展示了我使用的那個類,並提到了發生錯誤的那一行。我在attr和styles中應用了代碼。請提前幫助我。Android:在自定義開關佈局上發生錯誤

其中放在com.app.widgets包。

public class Switch extends CompoundButton 
{ 
// left and right text 
private CharSequence textLeft; 
private CharSequence textRight; 

public Context c; 

// the background 
private Drawable drawableBackground; 
// the switch 
private Drawable drawableSwitch; 
// helper for left and right text 
private Layout layoutLeft; 
private Layout layoutRight; 

// min width of the whole switch 
private int switchMinWidth; 

// actual width and height of the switch 
private int width; 
private int height; 

// the padding left+right inside of the switch 
private int innerPadding; 

// the space between the text to the left of the switch and the switch 
private int switchPadding; 

// the colors for the text of the switch 
private int textColorChecked; 
private int textColorUnChecked; 
private OnClickListener onClickListener; 

public Switch(Context context) { 
    this(context, null); 
    c = context; 
} 

public Switch(Context context, AttributeSet attrs) { 
    this(context, attrs, R.attr.switchStyle); 
    Log.e("log", "in Switch(Context context, AttributeSet attrs)"); 
    c = context; 
} 

public Switch(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 

    c = context; 

    this.getPaint().setAntiAlias(true); 

    Log.e("log", 
      "in Switch(Context context, AttributeSet attrs, int defStyle)"); 

    // load the default values 
    TypedArray a = context.obtainStyledAttributes(attrs, 
      R.styleable.Switch, defStyle, 0); 
    this.textLeft = a.getText(R.styleable.Switch_textLeft); 
    this.textRight = a.getText(R.styleable.Switch_textRight); 
    this.switchMinWidth = a.getDimensionPixelSize(
      R.styleable.Switch_switchMinWidth, 250); 
    this.textColorUnChecked = a.getColor(R.styleable.Switch_colorUnChecked, 
      Color.WHITE); 
    this.textColorChecked = a.getColor(R.styleable.Switch_colorChecked, 
      Color.WHITE); 
    this.drawableBackground = a 
      .getDrawable(R.styleable.Switch_backgroundDrawable); 
    this.drawableSwitch = a.getDrawable(R.styleable.Switch_switchDrawable); 
    this.switchPadding = a.getDimensionPixelSize(
      R.styleable.Switch_switchPadding, 32); 
    this.innerPadding = a.getDimensionPixelSize(
      R.styleable.Switch_innerPadding, 20); 
    this.setChecked(a.getBoolean(R.styleable.Switch_isChecked, false)); 
    a.recycle(); 

    // throw an error if the texts have not been set 
    if (this.textLeft == null || this.textRight == null) 
     throw new IllegalStateException(
       "Either textLeft or textRight is null. Please them via the attributes with the same name in the layout"); 
} 

public void setTextLeft(CharSequence textLeft) { 
    if (textLeft == null) 
     throw new IllegalArgumentException(
       "The text for the left side must not be null!"); 

    this.textLeft = textLeft; 
    this.requestLayout(); 
} 

public CharSequence getTextLeft() { 
    return this.textLeft; 
} 

public CharSequence getTextRight() { 
    return this.textRight; 
} 

public void setTextRight(CharSequence textRight) { 

    if (textRight == null) 
     throw new IllegalArgumentException(
       "The text for the right side must not be null!"); 

    this.textRight = textRight; 
    this.requestLayout(); 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    // create the helper layouts if necessary 
    if (this.layoutLeft == null) 
     this.layoutLeft = this.makeLayout(this.textLeft); 

    if (this.layoutRight == null) 
     this.layoutRight = this.makeLayout(this.textRight); 

    // find the larger text so both halfs of the switch are equally wide 
    final int maxTextWidth = Math.max(this.layoutLeft.getWidth(), 
      this.layoutRight.getWidth()); 

    // calculate the width for the whole switch 
    int actualWidth = Math.max(
      this.switchMinWidth, 
      maxTextWidth * 2 + this.getPaddingLeft() 
        + this.getPaddingRight() + this.innerPadding * 4); 



    final int switchHeight = Math.max(
      this.drawableBackground.getIntrinsicHeight(), // ****Error ON that line Which show the this.drawableBackground is null *******// 
      this.drawableSwitch.getIntrinsicHeight());// ****Error ON that line Which show the this.drawableSwitch is null *******// 

    this.width = actualWidth; 
    this.height = switchHeight; 

    // recalculate the width if there is a text 
    if (this.getText() != null) 
     actualWidth += this.makeLayout(this.getText()).getWidth() 
       + this.switchPadding; 

    // set the dimensions for this view 
    setMeasuredDimension(actualWidth, switchHeight); 
} 

@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) 
@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    // Display display = MyService.getScreenWidth(c); 

    int right; 
    if (AppConstants.ScreenWidth <= 480) { 

     right = this.getWidth() - 10; 
    } else { 
     right = this.getWidth() - this.getPaddingRight(); 
    } 
    // Log.e("LOG","width <>" + AppConstants.ScreenWidth); 

    int left; 
    if (AppConstants.ScreenWidth <= 480) { 
     left = right - ((int) (this.width/1.7)); 

    } else { 
     left = right - this.width; 
    } 

    // draw background 
    this.drawableBackground.setBounds(left, 0, right, this.height); 
    this.drawableBackground.draw(canvas); 

    if (AppConstants.ScreenWidth <= 480) { 
     if (this.isChecked()) 
      this.drawableSwitch.setBounds(left, 0, left 
        + ((int) (this.width/3.5)), this.height); 
     else 
      this.drawableSwitch.setBounds(left + (int) (this.width/3.5), 
        0, right, this.height); 

    } else { 
     if (this.isChecked()) 
      this.drawableSwitch.setBounds(left, 0, left + (this.width/2), 
        this.height); 
     else 
      this.drawableSwitch.setBounds(left + this.width/2, 0, right, 
        this.height); 

    } 

    this.drawableSwitch.draw(canvas); 

    // save canvas before translation (0x0) 
    canvas.save(); 

    if (AppConstants.ScreenWidth <= 480) { 

     // draw left text 
     this.getPaint().setColor(
       this.isChecked() ? this.textColorChecked 
         : this.textColorUnChecked); 
     this.getPaint().setTextSize(17); 

     canvas.translate(
       (float) (left + ((this.width/3.5) - (this.layoutLeft 
         .getWidth()))/2), (this.height - this.layoutLeft 
         .getHeight())/2); 
     this.layoutLeft.draw(canvas); 
     canvas.restore(); 

     // draw right text 
     this.getPaint().setColor(
       !this.isChecked() ? this.textColorChecked 
         : this.textColorUnChecked); 
     this.getPaint().setTextSize(17); 

     canvas.translate(
       (float) (left 
         + ((this.width/3.5) - this.layoutRight.getWidth()) 
         /2 + (this.width/3.5)), 
       (this.height - this.layoutRight.getHeight())/2); 
     this.layoutRight.draw(canvas); 
     canvas.restore(); 

    } else { 
     // draw left text 
     this.getPaint().setColor(
       this.isChecked() ? this.textColorChecked 
         : this.textColorUnChecked); 
     canvas.translate(
       left + (this.width/2 - this.layoutLeft.getWidth())/2, 
       (this.height - this.layoutLeft.getHeight())/2); 
     this.layoutLeft.draw(canvas); 
     canvas.restore(); 

     // draw right text 
     this.getPaint().setColor(
       !this.isChecked() ? this.textColorChecked 
         : this.textColorUnChecked); 
     canvas.translate(
       left + (this.width/2 - this.layoutRight.getWidth())/2 
         + this.width/2, 
       (this.height - this.layoutRight.getHeight())/2); 
     this.layoutRight.draw(canvas); 
     canvas.restore(); 
    } 
} 

@Override 
public int getCompoundPaddingRight() { 
    int padding = super.getCompoundPaddingRight() + this.width; 
    if (!TextUtils.isEmpty(getText())) 
     padding += this.switchPadding; 

    return padding; 
} 

@Override 
public void setOnClickListener(OnClickListener l) { 
    super.setOnClickListener(l); 

    this.onClickListener = l; 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    switch (event.getAction()) { 
    case MotionEvent.ACTION_DOWN: 
     this.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); 
     this.setChecked(!this.isChecked()); 
     invalidate(); 

     // call the onClickListener 
     if (this.onClickListener != null) 
      this.onClickListener.onClick(this); 
     return false; 
    } 
    return super.onTouchEvent(event); 
} 

private Layout makeLayout(CharSequence text) { 
    return new StaticLayout(text, this.getPaint(), 
      (int) FloatMath.ceil(Layout.getDesiredWidth(text, 
        this.getPaint())), Layout.Alignment.ALIGN_NORMAL, 1f, 
      0, true); 
} 

@Override 
protected void drawableStateChanged() { 
    // TODO don't use the 9-patches directly use a *.xml drawable instead 
    super.drawableStateChanged(); 

    int[] myDrawableState = getDrawableState(); 

    if (this.drawableSwitch != null) 
     this.drawableSwitch.setState(myDrawableState); 

    invalidate(); 
} 

public static class MyService { 
    public static int getScreenWidth(Activity activity) { 
     return activity.getWindowManager().getDefaultDisplay().getWidth(); 
    } 
} 
} 

XML

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="horizontal" 
    android:background ="@drawable/sectionlist" 
    xmlns:app="http://schemas.android.com/apk/res/com.example.app" 
    > 
<TextView 
    android:id="@+id/child_setting_header" 
    android:layout_width="match_parent" 
    android:layout_height="60dp" 
    android:lines="1" 
    android:layout_toRightOf="@+id/next" 
    android:gravity="center_vertical" 
    android:layout_centerVertical="true" 
    android:layout_gravity="center_vertical" 
    android:textColor="#FFFFFF" 
    android:text="Setting" 
    android:padding="8dp" 
    android:textSize="@dimen/largexhdpi_menuframe_child_section_textsize"/> 


<com.app.widgets.Switch 
    android:id="@+id/btn_checked_unchecked" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentRight="true" 
    android:layout_centerVertical="true" 
    android:layout_gravity="center_vertical" 
    android:gravity="right" 

    app:isChecked="true" 
    app:textLeft="English" 
    app:textRight="Hindi" 
    android:visibility="visible" /> 

<CheckBox 
    android:id="@+id/settings_check" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentRight="true" 
    android:layout_centerVertical="true" 
    android:layout_gravity="center_vertical" 
    android:gravity="right" 
    android:textColor="@color/menuframe_checkbox_textcolor" 
    android:visibility="visible" /> 

錯誤

03-07 12:32:24.141: E/AndroidRuntime(9984): FATAL EXCEPTION: main 

    03-07 12:32:24.141: E/AndroidRuntime(9984): Process: com.example.app, PID: 9984 
    03-07 12:32:24.141: E/AndroidRuntime(9984): java.lang.NullPointerException 

    03-07 12:32:24.141: E/AndroidRuntime(9984):  at com.app.widgets.Switch.onMeasure(Switch.java:160) 

    03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.view.View.measure(View.java:16458) 

    03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719) 
    03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455) 
    03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.view.View.measure(View.java:16458) 

    03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.widget.ListView.measureScrapChild(ListView.java:1200) 

    03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.widget.ListView.measureHeightOfChildren(ListView.java:1265) 

    03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.widget.ListView.onMeasure(ListView.java:1175) 

    03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.view.View.measure(View.java:16458) 

    03-07 12:32:24.141: E/AndroidRuntime(9984):  at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:666) 
    03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.View.measure(View.java:16458) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.View.measure(View.java:16458) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:327) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.View.measure(View.java:16458) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2289) 
03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.View.measure(View.java:16458) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1914) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1111) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1293) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5582) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.Choreographer.doCallbacks(Choreographer.java:562) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.Choreographer.doFrame(Choreographer.java:532) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.os.Handler.handleCallback(Handler.java:733) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.os.Handler.dispatchMessage(Handler.java:95) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.os.Looper.loop(Looper.java:137) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at android.app.ActivityThread.main(ActivityThread.java:4998) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at java.lang.reflect.Method.invokeNative(Native Method) 

03-07 12:32:24.141: E/AndroidRuntime(9984): at java.lang.reflect.Method.invoke(Method.java:515) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593) 

    03-07 12:32:24.141: E/AndroidRuntime(9984): at dalvik.system.NativeStart.main(Native Method) 

回答

2

後長time..I找到disturb.just溶液.sorry添加的XML。像

<com.app.widgets.Switch 
    android:id="@+id/btn_checked_unchecked" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentRight="true" 
    android:layout_centerVertical="true" 
    android:layout_gravity="center_vertical" 
    android:gravity="right" 

    app:isChecked="true" 
    app:textLeft="English" 
    app:textRight="Hindi" 
    app:backgroundDrawable="@drawable/switch_bg_holo_light" // added 
    app:switchDrawable="@drawable/switch_thumb_activated_holo_light"//added 
    android:visibility="visible" />