GVKun编程网logo

织梦用PHP判断flag自定义属性是否存在,然后调用自定义属性(phpstudy安装织梦)

32

本篇文章给大家谈谈织梦用PHP判断flag自定义属性是否存在,然后调用自定义属性,以及phpstudy安装织梦的知识点,同时本文还将给你拓展Android自定义View之自定义属性、android自定

本篇文章给大家谈谈织梦用PHP判断flag自定义属性是否存在,然后调用自定义属性,以及phpstudy安装织梦的知识点,同时本文还将给你拓展Android 自定义View之自定义属性、android 自定义控件 自定义属性详细介绍、Android 自定义控件之自定义属性、Android自定义控件——自定义属性等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

织梦用PHP判断flag自定义属性是否存在,然后调用自定义属性(phpstudy安装织梦)

织梦用PHP判断flag自定义属性是否存在,然后调用自定义属性(phpstudy安装织梦)

 

{dede:arclist typeid='1' flag='c'}

<li><a href=http://www.dede58.com/a/dedejq/"[field:arcurl/]">[field:title/]</a></li>

{/dede:arclist}

如果在新闻内容详细页把自定义属性调用出来用,试试用

{dede:field.flag/}

显示出来的是不是文字,而是

c,p

这是正常的,因为他只是调用数据表里的内容,如果要把指定的文字调用出来就需要array处理一下,用到PHP的strstr函数,下面给出办法

{dede:field name='array' runphp='yes'}

if(@me['typeid']=='1' && strstr(@me['flag'],'c')=='c') @me='[推荐]'.@me['title']';

else @me=@me['title'];

{/dede:field}

注意这个例子增加了栏目的ID判断条件,如果不需要判断就直接用

{dede:field name='array' runphp='yes'}

if(strstr(@me['flag'],'c')=='c') @me='[推荐]'.@me['title'];

else @me=@me['title'];

{/dede:field}

php判断字符串是否包含办法

办法一、使用strstr,strstr返回需要判断是否被包含的字符开始到结束的字符串,如果没有返回值,则不包含。

举例,判断是否包含字符“#”:

<?php

$str='abc#defg';

$in=strstr($str,'#');

echo $in;//输出结果为:#defg

?>

办法二、使用stristr,它的用法和strstr的完全一样。**的区别是stristr不区分大小写,而strstr区分大小写。可以根据实际情况是否区分大小写来使用。

办法三、使用strpos,但它对中文件的支持不是很好,它的返回值为boolean型,也就是true和false(真和假)。执行速度比stristr和strstr都快,strpos函数中有一个参数用于指定判断的位置,默认为空,即判断整个字符串。

下面看例子:

<?php

$str='bde';

$in='b';

$output=strpos($str,$in);

?>

办法四、将字符串用explode来拆分数组再判断。如下:

function chstr($str,$in){ $tmparr = explode($in,$str); if(count($tmparr)>1){ return true; }else{ return false; } } $str='abc#defg'; $in='#';//判断是否包含#这个字符 $bh=chstr($str,$in); if($bn){ echo '字符串'.$str.'包含'.$in; }else{ echo '字符串'.$str.'不包含'.$in; }  

本文章网址:http://www.ppssdd.com/code/11317.html。转载请保留出处,谢谢合作!

Android 自定义View之自定义属性

Android 自定义View之自定义属性

Android 自定义View之自定义属性

一:前言
image.png
1.什么是命名空间呢
android的命名空间和自定义命名空间
image.png

xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:前缀
android:名称,可以自定义
url:代表的就是空间,是个没有用的url,是统一资源标识符,相对于一个常量
2.配置文件attrs.xml
在res下的values文件加下创建一个attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomNumAnimView">
        <attr name="round_radius" format="dimension" />
        <attr name="round_color" format="color" />
        <attr name="text_color" format="color" />
        <attr name="text_size" format="dimension" />
    </declare-styleable>
</resources>

//格式解析
declare-styleable
name:属性集合名称
attr
name:属性名称
format:格式

共有11种格式
        1.reference(资源id)
    <ImageView android:background = "@drawable/图片ID"/>
    2.color
    <TextView android:textColor = "#00FF00" />
    3.boolean
    4.dimension(尺寸)(dp)
    5.float(浮点值)
    6.integer(整形值)
    7.string(字符串)
    8.fraction(百分比)
    9.enum(枚举值)
    <declare-styleable name="名称">
          <attr name="orientation">
      <enum name="horizontal" value="0" />
      <enum name="vertical" value="1" />
       </attr>
    </declare-styleable>
    10.flag(位或运算)
    注意:位运算类型的属性在使用的过程中可以使用多个值
    11.混合属性(使用|分开多个属性)

3.获取属性值

  public CustomNumAnimView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //获取自定义属性
        TypedArray array=context.obtainStyledAttributes(attrs,R.styleable.CustomNumAnimView,defStyleAttr,0);
     int roundColor=array.getColor(R.styleable.CustomNumAnimView_round_color, ContextCompat.getColor(context,R.color.purple_200));
    float roundRadius=array.getDimension(R.styleable.CustomNumAnimView_round_radius,50);
     int  textColor=array.getColor(R.styleable.CustomNumAnimView_text_color, Color.WHITE);
    float  textSize=array.getDimension(R.styleable.CustomNumAnimView_text_size,30);
        array.recycle();
    }

二:自定义View使用自定义属性

public class CustomNumAnimView extends View {

    private int roundColor;    //圆的颜色
    private int textColor;    //数字的颜色
    private float textSize;    //数字字体大小
    private float roundRadius;    //圆的半径

    private Paint mPaint;     //画笔
    private Rect textRect;    //包裹数字的矩形

    private boolean isFirstInit = false;   //是否是第一次初始化

    private CustomPoint leftPoint;    //左边的数字的实时点
    private String leftNum = "9";
    private ValueAnimator leftAnim;   //左边数字动画
    private boolean isLeftNumInvalidate = false;  //左边数字是否重绘界面

    private CustomPoint middlePoint;   //中间的数字的实时点
    private String middleNum = "9";
    private ValueAnimator middleAnim;   //中间数字动画
    private boolean isMiddleNumInvalidate = false;    //中间数字是否重绘界面

    private CustomPoint rightPoint;    //右边的数字的实时点
    private String rightNum = "9";
    private ValueAnimator rightAnim;   //右边数字动画
    private boolean isRightNumInvalidate = false;    //右边数字是否重绘界面


    public CustomNumAnimView(Context context) {
        this(context, null);
    }

    public CustomNumAnimView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomNumAnimView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //获取自定义属性
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CustomNumAnimView, defStyleAttr, 0);
        roundColor = array.getColor(R.styleable.CustomNumAnimView_round_color, ContextCompat.getColor(context, R.color.purple_200));
        roundRadius = array.getDimension(R.styleable.CustomNumAnimView_round_radius, 50);
        textColor = array.getColor(R.styleable.CustomNumAnimView_text_color, Color.WHITE);
        textSize = array.getDimension(R.styleable.CustomNumAnimView_text_size, 30);
        array.recycle();
        //创建画笔
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//抗锯齿标志
        mPaint.setTextSize(textSize);//画笔设置文本大小
        textRect = new Rect();
        //得到数字矩形的宽高,以用来画数字的时候纠正数字的位置
        mPaint.getTextBounds(middleNum, 0, middleNum.length(), textRect);
    }

    /**
     * 测量
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int size;
        int mode;
        int width;
        int height;
        size = MeasureSpec.getSize(widthMeasureSpec);
        mode = MeasureSpec.getMode(widthMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {    //确定的值或者MATCH_PARENT
            width = size;
        } else {    //表示WARP_CONTENT
            width = (int) (2 * roundRadius);
        }

        mode = MeasureSpec.getMode(heightMeasureSpec);
        size = MeasureSpec.getSize(heightMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {    //确定的值或者MATCH_PARENT
            height = size;
        } else {    //表示WARP_CONTENT
            height = (int) (2 * roundRadius);
        }
        setMeasuredDimension(width, height);
    }

    /**
     * 重写onDraw方法
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (!isFirstInit) {
            //是
            //初始化三串数字
            leftPoint = new CustomPoint(getMeasuredWidth() / 2 - textRect.width() / 2 - roundRadius / 2, (float) (getMeasuredHeight() / 2 - roundRadius * (Math.sqrt(3) / 2) - textRect.height() / 2));
            middlePoint = new CustomPoint(getMeasuredWidth() / 2 - textRect.width() / 2, getMeasuredHeight() / 2 - roundRadius - textRect.height() / 2);
            rightPoint = new CustomPoint(getMeasuredWidth() / 2 - textRect.width() / 2 + roundRadius / 2, (float) (getMeasuredHeight() / 2 - roundRadius * (Math.sqrt(3) / 2) - textRect.height() / 2));
            drawText(canvas);
            startAnimation();   //开始动画
            isFirstInit = true;

        } else {
            drawText(canvas);
        }
    }
    private boolean isAnimStart(ValueAnimator anim) {
        return !anim.isStarted();
    }
    public void startAnim() {
        if (isAnimStart(leftAnim)) {
            leftAnim.start();
        }
        if (isAnimStart(middleAnim)) {
            middleAnim.start();
        }
        if (isAnimStart(rightAnim)) {
            rightAnim.start();
        }
    }
    /**
     * 在onDestroy方法中调用
     */
    public void stopAnim() {
        leftAnim.end();
        middleAnim.end();
        rightAnim.end();
        leftAnim = null;
        middleAnim = null;
        rightAnim = null;
    }

    /**
     * 画数字
     */
    private void drawText(Canvas canvas) {
        //画圆
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setColor(roundColor);
        canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, roundRadius, mPaint);
        //写数字
        mPaint.setColor(textColor);
        mPaint.setTextSize(textSize);
        if (isLeftNumInvalidate) {
            canvas.drawText(leftNum, leftPoint.getX(), leftPoint.getY(), mPaint);
            isLeftNumInvalidate = false;
        }
        if (isMiddleNumInvalidate) {
            canvas.drawText(middleNum, middlePoint.getX(), middlePoint.getY(), mPaint);
            isMiddleNumInvalidate = false;
        }
        if (isRightNumInvalidate) {
            canvas.drawText(rightNum, rightPoint.getX(), rightPoint.getY(), mPaint);
            isRightNumInvalidate = false;
        }

    }

    /**
     * 开始动画
     */
    private void startAnimation() {
        startLeft();
        startMiddle();
        startRight();

    }

    private void startRight() {
        final CustomPoint startPoint = new CustomPoint(getMeasuredWidth() / 2 - textRect.width() / 2 + roundRadius / 2, (float) (getMeasuredHeight() / 2 - roundRadius * (Math.sqrt(3) / 2) - textRect.height() / 2));
        final CustomPoint endPoint = new CustomPoint(getMeasuredWidth() / 2 - textRect.width() / 2 + roundRadius / 2, (float) (getMeasuredHeight() / 2 + roundRadius * (Math.sqrt(3) / 2) + textRect.height() / 2));
        rightAnim = ValueAnimator.ofObject(new CustomPointEvaluator(), startPoint, endPoint);
        rightAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                rightPoint = (CustomPoint) animation.getAnimatedValue();
                isRightNumInvalidate = true;
                invalidate();
            }
        });
        rightAnim.addListener(new CustomAnimListener() {
            @Override
            public void onAnimationRepeat(Animator animation) {
                rightNum = getRandom();
            }
        });
        rightAnim.setStartDelay(150);
        rightAnim.setDuration(300);
        rightAnim.setRepeatCount(ValueAnimator.INFINITE);

    }

    private void startMiddle() {
        //初始化中间数字的开始点的位置
        final CustomPoint startPoint = new CustomPoint(getMeasuredWidth() / 2 - textRect.width() / 2, getMeasuredHeight() / 2 - roundRadius - textRect.height() / 2);
        //初始化中间数字的结束点的位置
        final CustomPoint endPoint = new CustomPoint(getMeasuredWidth() / 2 - textRect.width() / 2, getMeasuredHeight() / 2 + roundRadius + textRect.height() / 2);
        middleAnim = ValueAnimator.ofObject(new CustomPointEvaluator(), startPoint, endPoint);
        //监听从起始点到终点过程中点的变化,并获取点然后重新绘制界面
        middleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                middlePoint = (CustomPoint) animation.getAnimatedValue();
                isMiddleNumInvalidate = true;
                invalidate();
            }
        });
        middleAnim.addListener(new CustomAnimListener() {
            @Override
            public void onAnimationRepeat(Animator animation) {
                middleNum = getRandom();
            }
        });
        middleAnim.setDuration(300);
        middleAnim.setRepeatCount(ValueAnimator.INFINITE);

    }

    private void startLeft() {
        //属性动画
        final CustomPoint startPoint = new CustomPoint(getMeasuredWidth() / 2 - textRect.width() / 2 - roundRadius / 2, (float) (getMeasuredHeight() / 2 - roundRadius * (Math.sqrt(3) / 2) - textRect.height() / 2));
        final CustomPoint endPoint = new CustomPoint(getMeasuredWidth() / 2 - textRect.width() / 2 - roundRadius / 2, (float) (getMeasuredHeight() / 2 + roundRadius * (Math.sqrt(3) / 2) + textRect.height() / 2));
        leftAnim = ValueAnimator.ofObject(new CustomPointEvaluator(), startPoint, endPoint);
        leftAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                leftPoint = (CustomPoint) animation.getAnimatedValue();
                isLeftNumInvalidate = true;
                invalidate();
            }
        });
        leftAnim.addListener(new CustomAnimListener() {
            @Override
            public void onAnimationRepeat(Animator animation) {
                middleNum = getRandom();
            }
        });
        leftAnim.setStartDelay(100);
        leftAnim.setDuration(300);
        leftAnim.setRepeatCount(ValueAnimator.INFINITE);
    }


    /**
     * 获取0-9之间的随机数
     *
     * @return
     */
    private String getRandom() {
        int random = (int) (Math.random() * 9);
        return String.valueOf(random);
    }
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:lsp="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.ruan.mygitignore.CustomNumAnimView
        android:id="@+id/custom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        lsp:round_radius="50dp"
        lsp:text_size="16dp"/>
</LinearLayout>

这是一个自定view的使用的自定义属性

结尾:每一个小小的进步,都是日后的财富

android 自定义控件 自定义属性详细介绍

android 自定义控件 自定义属性详细介绍

自定义控件在android中无处不见,自定义控件给了我们很大的方便。比如说,一个视图为imageview ,imagebutton,textview 等诸多控件的组合,用的地方有很多,我们不可能每次都来写3个的组合,既浪费时间,效率又低。在这种情况下,我们就可以自定义一个view来替换他们,不仅提升了效率并且在xml中运用也是相当的美观。
一、控件自定义属性介绍
以下示例中代码均在values/attrs.xml 中定义,属性均可随意命名。
1. reference:参考某一资源ID。
示例:
[java]
复制代码 代码如下:

<declare-styleable name = "名称">
<attr name = "background" format = "reference" />
<attr name = "src" format = "reference" />
</declare-styleable>

2. color:颜色值。
示例:
[java]
复制代码 代码如下:

<declare-styleable name = "名称">
<attr name = "textColor" format = "color" />
</declare-styleable>

3. boolean:布尔值。
示例:
[java]
复制代码 代码如下:

<declare-styleable name = "名称">
<attr name = "focusable" format = "boolean" />
</declare-styleable>

4. dimension:尺寸值。
示例:
[java]
复制代码 代码如下:

<declare-styleable name = "名称">
<attr name = "layout_width" format = "dimension" />
</declare-styleable>

5. float:浮点值。
示例:
[java]
复制代码 代码如下:

<declare-styleable name = "名称">
<attr name = "fromAlpha" format = "float" />
<attr name = "toAlpha" format = "float" />
</declare-styleable>

6. integer:整型值。
示例:
[java]
复制代码 代码如下:

<declare-styleable name = "名称">
<attr name = "frameDuration" format="integer" />
<attr name = "framesCount" format="integer" />
</declare-styleable>

7. string:字符串。
示例:
[java]
复制代码 代码如下:

<declare-styleable name = "名称">
<attr name = "text" format = "string" />
</declare-styleable>

8. fraction:百分数。
示例:
[java]
复制代码 代码如下:

<declare-styleable name="名称">
<attr name = "pivotX" format = "fraction" />
<attr name = "pivotY" format = "fraction" />
</declare-styleable>

9. enum:枚举值。
示例:
[java]
复制代码 代码如下:

<declare-styleable name="名称">
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
</declare-styleable>

10. flag:位或运算。
示例:
[java]
复制代码 代码如下:

<declare-styleable name="名称">
<attr name="windowSoftInputMode">
<flag name = "stateUnspecified" value = "0" />
<flag name = "stateUnchanged" value = "1" />
<flag name = "stateHidden" value = "2" />
<flag name = "statealwaysHidden" value = "3" />
</attr>
</declare-styleable>

11.多类型。
示例:
[java]
复制代码 代码如下:

<declare-styleable name = "名称">
<attr name = "background" format = "reference|color" />
</declare-styleable>

-------------------------------------------------------------------------------------------
二、属性的使用以及自定义控件的实现
1、构思控件的组成元素,思考所需自定义的属性。
比如:我要做一个 <带阴影的按钮,按钮正下方有文字说明>(类似9宫格按钮)
新建values/attrs.xml
[java]
复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="custom_view">
<attr name="custom_id" format="integer" />
<attr name="src" format="reference" />
<attr name="background" format="reference" />
<attr name="text" format="string" />
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>

以上,所定义为custom_view,custom_id为按钮id,src为按钮,background为阴影背景,text为按钮说明,textColor为字体颜色,textSize为字体大小。
2、怎么自定义控件呢,怎么使用这些属性呢?话不多说请看代码,CustomView :
复制代码 代码如下:

package com.nanlus.custom;
import com.nanlus.custom.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
public class CustomView extends FrameLayout implements OnClickListener {
private CustomListener customListener = null;
private Drawable mSrc = null,mBackground = null;
private String mText = "";
private int mTextColor = 0;
private float mTextSize = 20;
private int mCustomId = 0;
private ImageView mBackgroundView = null;
private ImageButton mButtonView = null;
private TextView mTextView = null;
private LayoutParams mParams = null;
public CustomView(Context context) {
super(context);
}
public CustomView(Context context,AttributeSet attrs) {
super(context,attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.custom_view);
mSrc = a.getDrawable(R.styleable.custom_view_src);
mBackground = a.getDrawable(R.styleable.custom_view_background);
mText = a.getString(R.styleable.custom_view_text);
mTextColor = a.getColor(R.styleable.custom_view_textColor,
Color.WHITE);
mTextSize = a.getDimension(R.styleable.custom_view_textSize,20);
mCustomId = a.getInt(R.styleable.custom_view_custom_id,0);
mTextView = new TextView(context);
mTextView.setTextSize(mTextSize);
mTextView.setTextColor(mTextColor);
mTextView.setText(mText);
mTextView.setGravity(Gravity.CENTER);
mTextView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mButtonView = new ImageButton(context);
mButtonView.setimageDrawable(mSrc);
mButtonView.setBackgroundDrawable(null);
mButtonView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mButtonView.setonClickListener(this);
mBackgroundView = new ImageView(context);
mBackgroundView.setimageDrawable(mBackground);
mBackgroundView.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
addView(mBackgroundView);
addView(mButtonView);
addView(mTextView);
this.setonClickListener(this);
a.recycle();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mParams = (LayoutParams) mButtonView.getLayoutParams();
if (mParams != null) {
mParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
mButtonView.setLayoutParams(mParams);
}
mParams = (LayoutParams) mBackgroundView.getLayoutParams();
if (mParams != null) {
mParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
mBackgroundView.setLayoutParams(mParams);
}
mParams = (LayoutParams) mTextView.getLayoutParams();
if (mParams != null) {
mParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BottOM;
mTextView.setLayoutParams(mParams);
}
}
public void setCustomListener(CustomListener l) {
customListener = l;
}
@Override
public void onClick(View v) {
if (customListener != null) {
customListener.onCuscomClick(v,mCustomId);
}
}
public interface CustomListener {
void onCuscomClick(View v,int custom_id);
}
}

代码很简单,就不多说,下面来看看我们的CustomView是怎么用的,请看:
3、自定义控件的使用
话不多说,请看代码,main.xml:
[java]
复制代码 代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:nanlus="http://schemas.android.com/apk/res/com.nanlus.custom"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:orientation="horizontal" >
<com.nanlus.custom.CustomView
android:id="@+id/custom1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
nanlus:background="@drawable/background"
nanlus:custom_id="1"
nanlus:src="@drawable/style_button"
nanlus:text="按钮1" >
</com.nanlus.custom.CustomView>
</LinearLayout>
</RelativeLayout>

在这里需要解释一下,
xmlns:nanlus="http://schemas.android.com/apk/res/com.nanlus.custom"
nanlus为在xml中的前缀,com.nanlus.custom为包名
4、在Activity中,直接上代码
[java]
复制代码 代码如下:

package com.nanlus.custom;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.nanlus.BaseActivity;
import com.nanlus.custom.R;
import com.nanlus.custom.CustomView.CustomListener;
public class CustomActivity extends BaseActivity implements CustomListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((CustomView) this.findViewById(R.id.custom1)).setCustomListener(this);
}
@Override
public void onCuscomClick(View v,int custom_id) {
switch (custom_id) {
case 1:
Toast.makeText(this,"hello !!!",Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
}

Android 自定义控件之自定义属性

Android 自定义控件之自定义属性

前言

自定义控件可以说是 android 里的一个门槛,对很多 android 开发者来说可能都会认为比较难,当然这也是成为一个高手的必经之路,因此我准备在定义控件上多下些功夫,多花点时间研究,多写博客,如果想一起学习自定义控件,欢迎大家关注,如有疑问欢迎留言,如有谬误欢迎批评指正。

目录

通过本篇博客你将学到以下内容

1. 自定义控件的步骤

2. 自定义 view 中自定义属性的方法

3. 自定义属性中 format 10 中类型的详解

一、自定义控件步骤

1. 自定义 View 属性
2. 重写 onMeasure
3. 重写 onLayout
4. 重写 onDraw
今天这篇博客主要介绍第一步自定义属性,通过一个案例来进行讲解
案例的效果如下

即我们通过自定义 View 画一个圆,其中可以控制圆的半径大小和颜色,具体怎么做的呢?






二、自定义属性方法

1. 首先在 res/values/ 目录下创建 attrs 文件,如下所示

<declare-styleable name="CircleView">

      <attr name="circleRadius" format="dimension"/>
      <attr name="circleColor" format="color"/>
</declare-styleable>

WheelRecyclerView 是自己起的名字,不要与系统的冲突就行,
<attr name="circleRadius" format="dimension"/> 其中 name 就是自定义属性的名字(类似于系统控件的 android:layout_width) format 就是属性的类型,这里支持 10 种类型,如下图所示

我们先把这个小案例的流程走完,大家对流程熟悉之后再对细节进行讲解。


2. 编写自定义 View, 并在构造方法中获取我们自定义的属性


   public CircleView(Context context) {
        this(context,null);
    }

    public CircleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

	/**
     * 获取自定义属性
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public CircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

         TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.CircleView);
        /**
         * 获取圆的半径属性
         */
        circleRadius=ta.getDimension(R.styleable.CircleView_circleRadius,DEFAULT_RADIUS);
        /**
         * 获取圆的颜色属性
         */
        mColor=ta.getColor(R.styleable.CircleView_circleColor,DEFAULT_COLOR);
        ta.recycle();


        init();
    }

从上面可以看出,在一个参数的构造方法中,调用了两个参数的构造方法,然后在两个参数的构造方法中调用了三个参数的构造方法,然后通过 context 的 obtainStyledAttributes 方法可以得到一个 TypedArray 对象,这个对象里面封装了获取各个属性的方法,比如 getDimension,getColor,getFloat 等方法用来获取属性值。

3. 重写 onMeasure 方法

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        /**
         * Extracts the mode from the supplied measure specification
         * 从提供的测量规范中获取模式
         */
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        /**
         * Extracts the size from the supplied measure specification
         * 从提供的测量规范中获取大小
         */
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);

        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        int heightSize=MeasureSpec.getSize(heightMeasureSpec);
        /**
         * 如果宽度的测量模式是AT_MOST
         * 则设置宽度
         */
        if(widthMode==MeasureSpec.AT_MOST){

            widthSize= (int) (circleRadius*2+getPaddingLeft()+getPaddingRight());
        }

        if(heightMode==MeasureSpec.AT_MOST){

            heightSize= (int) (circleRadius*2+getPaddingTop()+getPaddingBottom());
        }

        setMeasuredDimension(widthSize,heightSize);
    }

上面我们重写了 onMeasure 方法,获取测量模式、获取控价大小并且按照我们自己的要求制定规则调用 setMeasuredDimension 此方法设置最终的宽和高。

4. 重写 onDraw 方法

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int paddingLeft=getPaddingLeft();
        int paddingTop=getPaddingTop();
        int paddingBottom=getPaddingBottom();
        int paddingRight=getPaddingRight();

        int width=getWidth()-paddingLeft-paddingRight;
        int height=getHeight()-paddingBottom-paddingTop;

        canvas.drawCircle(width/2+paddingLeft,height/2+paddingTop,circleRadius,mPaint);
    }

onDraw 方法很简单就是调用 canvas 的 drawCircle 方法,设置好圆的位置、半径和画笔画一个圆

到这里一个简单的自定义控件以及完成了,在布局中声明我们自定义的 View 如下:

<?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="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.example.video.CircleView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:padding="5dp"
        app:circleRadius="50dp"
        app:circleColor="#FF0000"/>

</LinearLayout>

运行即可看到文章开头的效果。

三、自定义属性 format 类型详解

接下来咱们对自定义属性时的 format 的类型做一下说明,format 的类型一共 10 中分别为:
string、boolean、color、dimension、enum、flags、float、fraction、integer、reference。

1.string

即字符串这个很好理解,类似于系统的 textview 设置 text 内容,在 attrs 中声明如下

<declare-styleable name="名称">
    <attr name="text" format="string"/>
</declare-styleable>

在布局中设置如下

app:text="Hello World!"

系统 textview 的 text 设置如下

android:text="hello world!!!"

2.boolean

布尔类型,有两个值 true 和 false, 类似于系统 Button 的 clickable 属性,在 attrs 中声明如下

<declare-styleable name="名称">
    <attr name="clickable" format="boolean"/>
</declare-styleable>

在布局中设置如下

app:clickable="true"

系统 button 的 clickable 设置如下

android:clickable="false"

3.color

设置颜色即设置 16 进制的颜色,在 attrs 中声明如下

<declare-styleable name="名称">
    <attr name="color" format="color"/>
</declare-styleable>

在布局中有如下两种设置方式

app:color="#FFFFFF"
app:color="@color/id"

系统中给 TextView 设置字体颜色

android:textColor="@color/colorPrimary"

4.dimension

设置尺寸值,一般用来设置 dp 值,在 attrs 中声明如下

<declare-styleable name="名称">
    <attr name="circleRadius" format="dimension" />
</declare-styleable>

在布局中可以进行如下设置

 app:circleRadius="50dp"

系统 textview 设置宽度的方法

 android:layout_width="50dp"

5.enum

设置枚举,一般有几个选项,用来选择,可以参考 LinearLayout 的 orientation 属性,在 attrs 中声明如下

<attr name="orientation">
    <enum name="horizontal" value="0"/>
    <enum name="vertical" value="1"/>
</attr>

在布局中可以进行如下的属性设置

enum

可以看到当我们输入 orientation 的时候会有两个选项就是我们上述 xml 中所声明的 horizontal 和 vertical

系统中的 LinearLayout 与之同理。

6.flags

位或运算即可以进行多个选择,在 atts 中声明如下

<declare-styleable name="CircleView">
     <attr name="gravity" format="flags">
         <flag name="top" value="0"/>
         <flag name="center" value="1"/>
         <flag name="right" value="2"/>
         <flag name="left" value="3"/>
     </attr>
</declare-styleable>

在布局中可以进行如下的属性设置

app:gravity="right|left|top"

7.float

浮点类型,在 attr 中声明如下

<declare-styleable name="CircleView"> 
   <attr name = "alpha" format="float" />
</declare-styleable>

在布局中可以对属性进行如下设置

app:alpha="0.8"

8.fraction

百分数,一般有两种

  • 100% 表示相对于对象自身的百分比
  • 100% p 表示相对于父容器的百分比,percent of parent
<declare-styleable name="CircleView">
   <attr name="progress" format="fraction"/>
</declare-styleable>

在布局中可以属性进行如下设置

app:progress="50%"

9.integer

整形,这个很简单,就不说了

10.reference

某一资源 ID,在 attr 中声明如下

<declare-styleable name="CircleView">
	<attr name="pic" format="reference"/>
</declare-styleable>

在布局中可以对属性进行如下设置

app:pic="@mipmap/ic_launcher"

好了以上就是对自定义属性内容的学习比较简单,但是也必须要从简单的学起,后续会逐步更新自定义 View 相关的内容,如有谬误欢迎批评指正,如果觉得本篇博客对你有帮助,就点个赞呗。

Android自定义控件——自定义属性

Android自定义控件——自定义属性

 我们在自定义Android组件的时候,除了用Java构建出组件的样子外,有时候还需要去申明一些“属性”提供给项目使用,那么什么是组件的属性呢?

例如在清单文件中,创建一个TextView的时候,这是需要制定TextView的 android:layout_width="wrap_content" android:layout_height="wrap_content"等等这些都是组件的属性,TextView是android系统为我们提供好 的组件,它的属性亦是android系统为我们提供了。详情查看android的源码,我这里举例android2.3的源码,路径是
/frameworks/base/core/res/res/values/attrs.xml,这个attrs.xml定义了所有android系统组件的属性。

当我们自定义组件时,除了可以使用android系统为我们提供好的属性之外,还可以自定义属性。自定义属性主要步骤如下:
一、在attrs.xml文件中声明属性,如:

[html] view plain copy

print?

  1. <declare-styleable name="MyToggleBtn">            // 声名属性集的名称,即这些属性是属于哪个控件的。  
  2. <attr name="current_state" format="boolean"/>   // 声名属性 current_state 格式为 boolean 类型  
  3. <attr name="slide_button" format="reference"/>   // 声名属性 slide_button格式为 reference 类型  
  4. </declare-styleable>   

所有的format类型
reference     引用
color            颜色
boolean       布尔值
dimension   尺寸值
float            浮点值
integer        整型值
string          字符串
enum          枚举值

二、在布局文件中使用:在使用之前必须声名命名空间,xmlns:example="http://schemas.android.com/apk/res/com.example.mytogglebtn"
说明:xmlns      是XML name space 的缩写; 
          example   可为任意写符       
          http://schemas.android.com/apk/res/    此为android固定格式;      

          com.example.mytogglebtn    此应用的包名,如manifest配置文件中一致。

布局文件:

 

[html] view plain copy

print?

  1. <com.example.mytogglebtn.MyToggleButton  
  2.     xmlns:example="http://schemas.android.com/apk/res/com.example.mytogglebtn"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="wrap_content"   
  5.     example:slide_button="@drawable/slide_button" />  

三、在代码中对属性进行解析,代码如下:

[java] view plain copy

print?

  1. TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleBtn);// 由attrs 获得 TypeArray  

以上是创建自定义属性的大致步骤。下面,我将要创建一个自定义控件的Demo,来学习学习自定义属性的相关知识点。

首先,需要创建一个自定义控件出来,并且继承View。在工程的res/values文件夹下创建attrs.xml文件:

 

[html] view plain copy

print?

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.     <!-- 声明属性级的名称 -->  
  5.     <declare-styleable name="MyView">  
  6.   
  7.         <!-- 声明一个属性,整型 -->  
  8.         <attr name="test_id" format="integer" />  
  9.         <!-- 声明一个属性,字符串 -->  
  10.         <attr name="test_msg" format="string" />  
  11.         <!-- 声明一个属性,引用,引用资源id -->  
  12.         <attr name="test_bitmap" format="reference" />  
  13.     </declare-styleable>  
  14.   
  15. </resources>  

然后在布局文件中,引用这个自定义控件MyView

 

 

[html] view plain copy

print?

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     xmlns:example="http://schemas.android.com/apk/res/com.example.myattrs"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent" >  
  6.   
  7.     <com.example.myattrs.MyView  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_centerInParent="true"  
  11.         example:test_bitmap="@drawable/ic_launcher"  
  12.         example:test_msg="@string/app_name" />  
  13.   
  14. </RelativeLayout>  

 

由于创建出来的自定义组件MyView是继承于View的,所以必须得复写View的构造方法,View中有三个构造方法,先来看看复写带一个参数的构造方法:

 

[java] view plain copy

print?

  1. package com.example.myattrs;  
  2.   
  3. import android.content.Context;  
  4. import android.view.View;  
  5.   
  6. public class MyView extends View {  
  7.   
  8.     public MyView(Context context) {  
  9.         super(context);  
  10.         // TODO Auto-generated constructor stub  
  11.     }  
  12. }  

运行一下工程,那么工程立即崩溃了,报错也很清晰明了:

 

09-17 06:52:24.389: E/AndroidRuntime(1563): Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]

表示没有找到某个带两个参数的构造方法,于是,知道自定义属性必须得复写父类的另外一个构造方法,修改如下:

 

[java] view plain copy

print?

  1. package com.example.myattrs;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5. import android.view.View;  
  6.   
  7. public class MyView extends View {  
  8.   
  9.     public MyView(Context context, AttributeSet attrs) {  
  10.         super(context, attrs);  
  11.   
  12.         int count = attrs.getAttributeCount();  
  13.         for (int index = 0; index < count; index++) {  
  14.             String attributeName = attrs.getAttributeName(index);  
  15.             String attributeValue = attrs.getAttributeValue(index);  
  16.             System.out.println("name:" + attributeName + "  value:" + attributeValue);  
  17.         }  
  18.     }  
  19.   
  20. }  

打印结果如下:

 

AttributeSet:对布局文件XML解析后的结果,封装为AttributeSet对象。存储的都是原始数据,但是对数据进行了简单的加工。

由此构造器帮我们返回了布局文件XML的解析结果,拿到这个结果,我们该怎么做呢?接下来,我们来看看View类对于这个是怎么处理的:

 

[java] view plain copy

print?

  1. public View(Context context, AttributeSet attrs) {  
  2.         this(context, attrs, 0);  
  3.     }  

[java] view plain copy

print?

  1. public View(Context context, AttributeSet attrs, int defStyle) {  
  2.         this(context);  
  3.   
  4.         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,  
  5.                 defStyle, 0);  

于是,找到一个跟属性很相关的类TypeArray,那么接下来,我在自定义控件的构造方法上也获取一下TypeArray这个类:

翻看一下TypeArray的源码会发现,TypeArray是不继承任何类(除了Object)的,也就是说,TypeArray相当于一个工具 类,通过context.obtainStyledAttributes方法,将AttributeSet和属性的类型传递进去,比如 AttributeSet相当于原材料,属性类型相当于图纸,context.obtainStyledAttributes相当于加工厂加工成所对象的 属性,封装到TypeArray这个类里。

 

[java] view plain copy

print?

  1. package com.example.myattrs;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.util.AttributeSet;  
  6. import android.view.View;  
  7.   
  8. public class MyView extends View {  
  9.   
  10.     public MyView(Context context, AttributeSet attrs) {  
  11.         super(context, attrs);  
  12.   
  13.         TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyView);  
  14.         int count = ta.getIndexCount();  
  15.         for (int i = 0; i < count; i++) {  
  16.             int itemId = ta.getIndex(i);  
  17.             System.out.println("itemId::" + itemId); // 获取属性在R.java文件中的id  
  18.             switch (itemId) {  
  19.             case R.styleable.MyView_test_bitmap:  
  20.                 int bitmapId = ta.getResourceId(itemId, 100);  
  21.                 System.out.println("bitmapId::" + bitmapId);  
  22.                 break;  
  23.             case R.styleable.MyView_test_id:  
  24.                 int test_id = ta.getInteger(itemId, 10);  
  25.                 System.out.println("test_id" + test_id);  
  26.                 break;  
  27.             case R.styleable.MyView_test_msg:  
  28.                 String test_msg = ta.getString(itemId);  
  29.                 System.out.println("test_msg::" + test_msg);  
  30.                 break;  
  31.             default:  
  32.                 break;  
  33.             }  
  34.         }  
  35.     }  
  36.   
  37. }  

 

以下是TypeArray类里的方法,这里不写注释了,见名知意:

当在构造方法中获取到这些设置好的属性值时,取出其值,就可以在代码中进行处理了。

上篇博客提到了Android自定义控件——仿ios的滑动开关按钮,接下来,就要为这个滑动开关按钮条件自定义的属性,不熟悉上篇博客Demo的,可以先去浏览器一下我的上篇博客,点这里Android自定义控件——仿ios滑动开关按钮

首先,按照上面介绍的步骤,先在res/values目录下创建一个属性文件attrs.xml:

 

[html] view plain copy

print?

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.     <declare-styleable name="MyToggleBtn">  
  5.   
  6.         <!-- 滑动按钮背景图片 -->  
  7.         <attr name="switchBG" format="reference" />  
  8.         <!-- 滑动块图片 -->  
  9.         <attr name="slideBg" format="reference" />  
  10.         <!-- 设置当前的状态 -->  
  11.         <attr name="currState" format="boolean" />  
  12.     </declare-styleable>  
  13.   
  14. </resources>  

然后,在引用自定义控件的布局文件acticity_main.xml上设置自定义属性,记住,引用这些属性之前,必须先引用命名空间:

 

xmlns:mytogglebtn="http://schemas.android.com/apk/res/com.example.slidebutton"

其中:mytogglebtn 是任意取名,没有强制要求,但是在控件中引用属性的时候,要保持一致,不要写错了

          com.example.slidebutton 是工程的包名,千万不要弄错了,不然找不到属性文件

 

[html] view plain copy

print?

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     xmlns:mytogglebtn="http://schemas.android.com/apk/res/com.example.slidebutton"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent" >  
  6.   
  7.     <com.example.slidebutton.view.SlideButton  
  8.         android:id="@+id/slidebutton"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:layout_centerInParent="true"  
  12.         mytogglebtn:currState="false"  
  13.         mytogglebtn:slideBg="@drawable/slide_button_background"  
  14.         mytogglebtn:switchBG="@drawable/switch_background" />  
  15.   
  16. </RelativeLayout>  

有了上面的步骤,我们就可以自定义组件类的构造方法中,将属性集解析成TypeArray了,从TypeArray中获取相关的属性值,并用于初始化自定义控,以下是主要代码:

 

 

[java] view plain copy

print?

  1. public SlideButton(Context context, AttributeSet attrs) {  
  2.         super(context, attrs);  
  3.   
  4.         // 获得自定义属性  
  5.         TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleBtn);  
  6.   
  7.         int count = ta.getIndexCount();  
  8.         for (int i = 0; i < count; i++) {  
  9.             int itemId = ta.getIndex(i); // 获取某个属性的Id值  
  10.             switch (itemId) {  
  11.             case R.styleable.MyToggleBtn_currState: // 设置当前按钮的状态  
  12.                 currentState = ta.getBoolean(itemId, false);  
  13.                 break;  
  14.             case R.styleable.MyToggleBtn_switchBG: // 设置按钮的背景图  
  15.                 int backgroundId = ta.getResourceId(itemId, -1);  
  16.                 if (backgroundId == -1)  
  17.                     throw new RuntimeException("资源没有被找到,请设置背景图");  
  18.                 switchBG = BitmapFactory.decodeResource(getResources(), backgroundId);  
  19.                 break;  
  20.             case R.styleable.MyToggleBtn_slideBg: // 设置按钮图片  
  21.                 int slideId = ta.getResourceId(itemId, -1);  
  22.                 if (slideId == -1)  
  23.                     throw new RuntimeException("资源没有找到,请设置按钮图片");  
  24.                 slideButtonBG = BitmapFactory.decodeResource(getResources(), slideId);  
  25.                 break;  
  26.             default:  
  27.                 break;  
  28.             }  
  29.         }  
  30.     }  

 

        从上可以看到,自定义属性其实很简单。就是在构造方法中,将获取到的属性集加工成TypeArray对象,通过这个对象取出属性的id,通过id取出每个 属性对应的值(毕竟Android下的布局文件XML也是key-value形式的),最后将获取到的属性值(控件用户自定义的数据)初始化到自定义控件 上,这样,一个完整的自定义控件就完成。这种完整的自定义控件方式用的并不多见,因为在开发自定义控件时候,需要什么数据就直接在Java代码里设置就好 了,方便多了。但是在特定的场合下,如果开发的控件某些数据不确定,或者所开发控件需要提供给其他人进行偏好设置什么的,这种自定义属性就显得非用不可 了。

我们今天的关于织梦用PHP判断flag自定义属性是否存在,然后调用自定义属性phpstudy安装织梦的分享就到这里,谢谢您的阅读,如果想了解更多关于Android 自定义View之自定义属性、android 自定义控件 自定义属性详细介绍、Android 自定义控件之自定义属性、Android自定义控件——自定义属性的相关信息,可以在本站进行搜索。

本文标签: