Android 技巧

1.自定义Styles 统一组件风格

# styles.xml
<resources>

    <style name="FormRadioButton"       parent="android:Widget.CompoundButton.RadioButton">
        <item name="android:minHeight">@dimen/buttonHeight</item>
        <item name="android:button">@null</item>
        <item name="android:background">@drawable/background_radio</item>
        <item name="android:gravity">center</item>
    </style>

</resources>


# activity_layout.xml

<RadioGroup
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <RadioButton
            style="@style/FormRadioButton"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="One"/>
        <RadioButton
            style="@style/FormRadioButton"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Two"/>
        <RadioButton
            style="@style/FormRadioButton"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Three"/>
</RadioGroup>

2.自定义View

public class BullsEyeView extends View {
    private Paint mPaint;
    private Point mCenter;
    private float mRadius;

    /*
     * Java Constructor
     */
    public BullsEyeView(Context context) {
        this(context, null);
    }

    /*
     * XML Constructor
     */
    public BullsEyeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    /*
     * XML Constructor with Style
     */
    public BullsEyeView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        //在这里可以做自定义View的一些初始化配置

        //例如,创建一个可绘画的刷子
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        //设置刷子的风格
        mPaint.setStyle(Style.FILL);

        //创建绘画的中心点
        mCenter = new Point();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width, height;

        //设置大小
        int contentWidth = 200;
        int contentHeight = 200;
        width = getMeasurement(widthMeasureSpec, contentWidth);
        height = getMeasurement(heightMeasureSpec, contentHeight);

        //必须调用此方法
        setMeasuredDimension(width, height);
    }

    /*
     * 辅助设置大小的方法
     */
    private int getMeasurement(int measureSpec, int contentSize) {
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (MeasureSpec.getMode(measureSpec)) {
            case MeasureSpec.AT_MOST:
                return Math.min(specSize, contentSize);
            case MeasureSpec.UNSPECIFIED:
                return contentSize;
            case MeasureSpec.EXACTLY:
                return specSize;
            default:
                return 0;
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (w != oldw || h != oldh) {
            //如果大小有变,要重置中心点以及半径
            mCenter.x = w / 2;
            mCenter.y = h / 2;
            mRadius = Math.min(mCenter.x, mCenter.y);
        } 
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //绘制圆形
        // 用不同颜色从最小到最大绘制
        mPaint.setColor(Color.RED);
        canvas.drawCircle(mCenter.x, mCenter.y, mRadius, mPaint);
        mPaint.setColor(Color.WHITE);
        canvas.drawCircle(mCenter.x, mCenter.y, mRadius * 0.8f, mPaint);
        mPaint.setColor(Color.BLUE);
        canvas.drawCircle(mCenter.x, mCenter.y, mRadius * 0.6f, mPaint);
        mPaint.setColor(Color.WHITE);
        canvas.drawCircle(mCenter.x, mCenter.y, mRadius * 0.4f, mPaint);
        mPaint.setColor(Color.RED);
        canvas.drawCircle(mCenter.x, mCenter.y, mRadius * 0.2f, mPaint); 
    }
}

3.View动画

View.animate()
ObjectAnimator
AnimatorSet

4.Layout动画

removeView(View)
addView(View, LayoutParams)
layout.xml需要添加:android:animateLayoutChanges="true"
Layout.setLayoutTransition(LayoutTransition)

5.自定义ListView

# res/drawable/row_background_default.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:startColor="#EFEFEF"
        android:endColor="#989898"
        android:type="linear"
        android:angle="270" /> 
</shape>

# res/drawable/row_background_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:startColor="#0B8CF2"
        android:endColor="#0661E5"
        android:type="linear"
        android:angle="270" /> 
</shape>

# res/drawable/row_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/row_background_pressed"/>
    <item android:drawable="@drawable/row_background_default"/>
</selector>


# res/layout/custom_row.xml
<?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:padding="10dip"
    android:background="@drawable/row_background">
    <TextView
        android:id="@+id/line1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"    />
</LinearLayout>

6.简洁易懂的自定义组件

public class TextImageButton extends FrameLayout {
    private ImageView imageView;
    private TextView textView;

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

    public TextImageButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TextImageButton(Context context, AttributeSet attrs,
            int defaultStyle) {
        // 用默认button风格初始化layout
        // 当前主题设置了可点击属性以及背景
        super(context, attrs, android.R.attr.buttonStyle);
        //创建子类视图
        imageView = new ImageView(context, attrs, defaultStyle);
        textView = new TextView(context, attrs, defaultStyle);
        //为子类视图创建LayoutParams
        FrameLayout.LayoutParams params = new 
            FrameLayout.LayoutParams(
            LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT, 
            Gravity.CENTER);

        //添加子类视图
        this.addView(imageView, params);
        this.addView(textView, params);

        //如果有图片,显示图片
        if(imageView.getDrawable() != null) {
            textView.setVisibility(View.GONE);
            imageView.setVisibility(View.VISIBLE);
        } else {
            textView.setVisibility(View.VISIBLE);
            imageView.setVisibility(View.GONE);
        }
    }

    /* 属性设置 */
    public void setText(CharSequence text) {
        //切换至Text视图
        textView.setVisibility(View.VISIBLE);
        imageView.setVisibility(View.GONE);
        //设置Text值
        textView.setText(text);
    }

    public void setImageResource(int resId) {
        //切换至图片视图
        textView.setVisibility(View.GONE);
        imageView.setVisibility(View.VISIBLE);
        //设置图片资源
        imageView.setImageResource(resId);
    }

    public void setImageDrawable(Drawable drawable) {
        //切换至图片视图
        textView.setVisibility(View.GONE);
        imageView.setVisibility(View.VISIBLE);
        //设置图片Drawable
        imageView.setImageDrawable(drawable);
    }
}

7.自定义过渡动画

# startActivity()后的动画
res/anim/activity_open_enter.xml
res/anim/activity_open_exit.xml

# finish()后的动画
res/anim/activity_close_enter.xml
res/anim/activity_close_exit.xml


# res/anim/xxxx.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <rotate
        android:fromDegrees="90" android:toDegrees="0"
        android:pivotX="0%" android:pivotY="0%"
        android:fillEnabled="true"
        android:fillBefore="true" android:fillAfter="true"
        android:duration="500"  />
    <alpha
        android:fromAlpha="0.0" android:toAlpha="1.0"
        android:fillEnabled="true"
        android:fillBefore="true" android:fillAfter="true"
        android:duration="500" />
</set>

//开启新的acitvity的动画效果
Intent intent = new Intent(...);
startActivity(intent);
overridePendingTransition(R.anim.activity_open_enter, R.anim.activity_open_exit);
//关闭当前activity的动画效果
finish();
overridePendingTransition(R.anim.activity_close_enter, R.anim.activity_close_exit);

# res/values/styles.xml
<resources>
    <style name="AppTheme" parent="android:Theme.Holo.Light">
        <item name="android:windowAnimationStyle">
            @style/ActivityAnimation</item>
    </style>

    <style name="ActivityAnimation"
        parent="@android:style/Animation.Activity">
        <item name="android:activityOpenEnterAnimation">
            @anim/activity_open_enter</item>
        <item name="android:activityOpenExitAnimation">
            @anim/activity_open_exit</item>
        <item name="android:activityCloseEnterAnimation">
            @anim/activity_close_enter</item>
        <item name="android:activityCloseExitAnimation">
            @anim/activity_close_exit</item>
    </style>
</resources>
  • 支持库中的Fragments的用法
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    //必须第一个调用
    ft.setCustomAnimations(R.anim.activity_open_enter,
            R.anim.activity_open_exit,
            R.anim.activity_close_enter,
            R.anim.activity_close_exit);
    ft.replace(R.id.container_fragment, fragment);
    ft.addToBackStack(null);
ft.commit();

或者
// 覆写onCreateAnimation()方法
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
    switch (transit) {
        case FragmentTransaction.TRANSIT_FRAGMENT_FADE:
            if (enter) {
                return AnimationUtils.loadAnimation(getActivity(),
                        android.R.anim.fade_in);
            } else {
                return AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out);
            }
        case FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
            if (enter) {
                return AnimationUtils.loadAnimation(getActivity(), R.anim.activity_close_enter);
            } else {
                return AnimationUtils.loadAnimation(getActivity(), R.anim.activity_close_exit);
            }
        case FragmentTransaction.TRANSIT_FRAGMENT_OPEN:
        default:
            if (enter) {
                return AnimationUtils.loadAnimation(getActivity(), R.anim.activity_open_enter);
            } else {
                return AnimationUtils.loadAnimation(getActivity(), R.anim.activity_open_exit);
            }
    }
}

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    //设置动画效果
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    ft.replace(R.id.container_fragment, fragment);
    ft.addToBackStack(null);
ft.commit();

8.创建View的变化

@Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
    // 清除已有的变化
    t.clear();
    if (getOrientation() == HORIZONTAL) {
        // 基于离左边缘距离来改变子类View
        float delta = 1.0f - ((float) child.getLeft() / getWidth());
        t.getMatrix().setScale(delta, delta, child.getWidth() / 2, child.getHeight() / 2);
    } else {
        //基于离上边缘距离来改变子类View
        float delta = 1.0f - ((float) child.getTop() / getHeight());
        t.getMatrix().setScale(delta, delta, child.getWidth() / 2, child.getHeight() / 2);
        //基于子类View的位置渐变
        t.setAlpha(delta);
    }
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值