自定义控件
旋转动画工具类
package com.gordon.youku;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
/**
* Created by Kevin.
*/
public class AnimUtils {
//利用重载, 可以在不改变原来api的情况下, 增添新的参数
public static void show(ViewGroup view) {
show(view, 0);
}
public static void hide(ViewGroup view) {
hide(view, 0);
}
//隐藏, 旋转动画
public static void hide(ViewGroup view, long delay) {
//围绕底边中心点旋转
RotateAnimation anim = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 1);
anim.setDuration(500);
anim.setFillAfter(true);//动画结束后保持住当时状态
anim.setStartOffset(delay);//延时多长时间之后再启动动画
view.startAnimation(anim);
//禁用所有按钮的点击事件
int childCount = view.getChildCount();//子控件个数
for (int i = 0; i < childCount; i++) {
View child = view.getChildAt(i);//获取第i个子控件
child.setEnabled(false);//禁用
}
}
//显示, 旋转动画
public static void show(ViewGroup view, long delay) {
//围绕底边中心点旋转
RotateAnimation anim = new RotateAnimation(180, 360, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 1);
anim.setDuration(500);
anim.setFillAfter(true);//动画结束后保持住当时状态
anim.setStartOffset(delay);//延时多长时间之后再启动动画
view.startAnimation(anim);
//启用所有按钮的点击事件
int childCount = view.getChildCount();//子控件个数
for (int i = 0; i < childCount; i++) {
View child = view.getChildAt(i);//获取第i个子控件
child.setEnabled(true);//启用
}
}
}
主函数
package cn.itcast.youku11;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ImageView ivHome;
private ImageView ivMenu;
private RelativeLayout rlLevel1;
private RelativeLayout rlLevel2;
private RelativeLayout rlLevel3;
private boolean isLevel3Show = true;//标记布局是否显示
private boolean isLevel2Show = true;//标记布局是否显示
private boolean isLevel1Show = true;//标记布局是否显示
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivHome = (ImageView) findViewById(R.id.iv_home);
ivMenu = (ImageView) findViewById(R.id.iv_menu);
rlLevel1 = (RelativeLayout) findViewById(R.id.rl_level1);
rlLevel2 = (RelativeLayout) findViewById(R.id.rl_level2);
rlLevel3 = (RelativeLayout) findViewById(R.id.rl_level3);
ivHome.setOnClickListener(this);
ivMenu.setOnClickListener(this);
//如果给第三层布局加点击事件, 会导致home和menu按钮无法点击
//解决办法: 将第三层布局写在最底下, 第一层写在最上面, 就不会挡住点击事件了
rlLevel3.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_home:
System.out.println("home clicked!!!");
//如果显示则隐藏;反之亦然
if (isLevel2Show) {
AnimUtils.hide(rlLevel2);
isLevel2Show = false;
//如果level3显示, 也要隐藏
if (isLevel3Show) {
AnimUtils.hide(rlLevel3, 200);
isLevel3Show = false;
}
} else {
AnimUtils.show(rlLevel2);
isLevel2Show = true;
}
break;
case R.id.iv_menu:
System.out.println("menu clicked!!!");
//如果显示则隐藏;反之亦然
if (isLevel3Show) {
AnimUtils.hide(rlLevel3);
isLevel3Show = false;
} else {
AnimUtils.show(rlLevel3);
isLevel3Show = true;
}
break;
default:
break;
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
//拦截物理按键
//拦截不了: home键, 电源键
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
System.out.println("当前按键:" + keyCode);
//物理菜单键
if (keyCode == KeyEvent.KEYCODE_MENU) {
if (isLevel1Show) {
AnimUtils.hide(rlLevel1);
isLevel1Show = false;
if (isLevel2Show) {
AnimUtils.hide(rlLevel2, 200);
isLevel2Show = false;
}
if (isLevel3Show) {
AnimUtils.hide(rlLevel3, 300);
isLevel3Show = false;
}
} else {
AnimUtils.show(rlLevel1);
AnimUtils.show(rlLevel2, 200);
isLevel1Show = true;
isLevel2Show = true;
}
return true;//表示已经处理完事件
}
return super.onKeyDown(keyCode, event);
}
}
效果
**点击事件bug 动画只是假象,点击事件依然存在 **
//禁用所有按钮的点击事件
int childCount = view.getChildCount();//子控件个数
for (int i = 0; i < childCount; i++) {
View child = view.getChildAt(i);//获取第i个子控件
child.setEnabled(false);//禁用
}
07 ViewPager的使用
在这里插入代码片
08 ViewPager循环滑动效果
效果1:
@Override
public int getCount() {
//return mImageIds.length;
return Integer.MAX_VALUE;
}
//初始化条目布局对象,类似getView
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
//当前位置对集合大小取余,返回0-4的位置信息
position = position % mImageIds.length;
//初始化条目布局
ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageResource(mImageIds[position]);
//将条目布局添加给viewpager
container.addView(imageView);
System.out.println("初始化条目:" + position);
//返回布局对象
return imageView;
}
效果2:
//设置开始时左右都能滑
mViewPager.setCurrentItem(Integer.MAX_VALUE/2);
mViewPager.setCurrentItem(mImageIds.length*100000);
09.广告条加标题栏
<FrameLayout
android:layout_width="match_parent"
android:layout_height="180dp">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="wrap_content"
android:layout_height="180dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#a000"
android:orientation="vertical"
android:layout_gravity="bottom"
android:padding="5dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题" />
</LinearLayout>
</FrameLayout>
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float posOffset, int posOffsetPixels) {}
@Override
public void onPageSelected(int position) {
position = position % mImageIds.length;
tvTitle.setText(mImageDes[position]);
}
@Override
public void onPageScrollStateChanged(int state) {}
});
tvTitle.setText(mImageDes[0]);
10.小圆点逻辑处理
布局:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#f00" />
<size
android:width="5dp"
android:height="5dp" />
</shape>
//动态初始化小圆点
for (int i = 0; i < mImageIds.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setImageResource(R.drawable.shape_gray);
//动态设置边距
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
//从第二个点设置边距
if (i > 0) {
lp.leftMargin = 10;
}
imageView.setLayoutParams(lp);
//将小圆点添加到线性布局(5个小圆点)
llContainer.addView(imageView);
}
@Override
public void onPageSelected(int position) {
position = position % mImageIds.length;
tvTitle.setText(mImageDes[position]);
for (int i = 0; i < mImageIds.length; i++) {
ImageView image = (ImageView) llContainer.getChildAt(i);
if (i != position) {
image.setImageResource(R.drawable.shape_gray);
} else {
image.setImageResource(R.drawable.shape_red);
}
}
//切换红点图片
ImageView imageView = (ImageView) llContainer.getChildAt(position);
imageView.setImageResource(R.drawable.shape_red);
}
11.广告条自动轮播效果
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//切换到下个页面
int currentItem = mViewPager.getCurrentItem();
currentItem++;
mViewPager.setCurrentItem(currentItem);
mHandler.sendEmptyMessageDelayed(0,3000);
}
};
mHandler.sendEmptyMessageDelayed(0, 3000);
12.广告条触摸响应
按住停止自动发消息,抬起时继续发消息
mViewPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//停止轮播
mHandler.removeCallbacksAndMessages(null);
break;
case MotionEvent.ACTION_UP:
mHandler.sendEmptyMessageDelayed(0,3000);
break;
case MotionEvent.ACTION_MOVE:
break;
}
return false;
}
});
完整代码
package com.gordon.viewpager;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private final String[] mImageDes = {"巩俐不低俗,我就不能低俗", "朴树又回来啦!再唱经典老歌引万人大合唱", "揭秘北京电影如何升级",
"乐视网TV版大派送", "热血屌丝的反杀"};
private final int[] mImageIds = new int[]{R.drawable.a, R.drawable.b, R.drawable.c, R
.drawable.d, R.drawable.e};
private ViewPager mViewPager;
private TextView tvTitle;
private LinearLayout llContainer;
private ImageView imageView;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//切换到下个页面
int currentItem = mViewPager.getCurrentItem();
currentItem++;
mViewPager.setCurrentItem(currentItem);
mHandler.sendEmptyMessageDelayed(0, 3000);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTitle = findViewById(R.id.tv_title);
llContainer = findViewById(R.id.ll_container);
mViewPager = findViewById(R.id.view_pager);
MyAdapter myAdapter = new MyAdapter();
mViewPager.setAdapter(myAdapter);
//设置开始时左右都能滑
mViewPager.setCurrentItem(Integer.MAX_VALUE / 2);
mViewPager.setCurrentItem(mImageIds.length * 100000);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float posOffset, int posOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
position = position % mImageIds.length;
tvTitle.setText(mImageDes[position]);
for (int i = 0; i < mImageIds.length; i++) {
ImageView image = (ImageView) llContainer.getChildAt(i);
if (i != position) {
image.setImageResource(R.drawable.shape_gray);
} else {
image.setImageResource(R.drawable.shape_red);
}
}
//切换红点图片
ImageView imageView = (ImageView) llContainer.getChildAt(position);
imageView.setImageResource(R.drawable.shape_red);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
tvTitle.setText(mImageDes[0]);
//动态初始化小圆点
for (int i = 0; i < mImageIds.length; i++) {
imageView = new ImageView(this);
imageView.setImageResource(R.drawable.shape_gray);
//动态设置边距
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
//从第二个点设置边距
if (i > 0) {
lp.leftMargin = 10;
imageView.setImageResource(R.drawable.shape_gray);
} else {
imageView.setImageResource(R.drawable.shape_red);
}
imageView.setLayoutParams(lp);
//将小圆点添加到线性布局(5个小圆点)
llContainer.addView(imageView);
}
mHandler.sendEmptyMessageDelayed(0, 3000);
mViewPager.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//停止轮播
mHandler.removeCallbacksAndMessages(null);
break;
case MotionEvent.ACTION_UP:
mHandler.sendEmptyMessageDelayed(0,3000);
break;
case MotionEvent.ACTION_MOVE:
break;
}
return false;
}
});
}
class MyAdapter extends PagerAdapter {
public MyAdapter() {}
@Override
public int getCount() {
//return mImageIds.length;
return Integer.MAX_VALUE;
}
//判断显示的view是不是就是返回的object对象,只有是true,才显示,否则不显示
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
//初始化条目布局对象,类似getView
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
//当前位置对集合大小取余,返回0-4的位置信息
position = position % mImageIds.length;
//初始化条目布局
ImageView imageView = new ImageView(MainActivity.this);
imageView.setImageResource(mImageIds[position]);
//将条目布局添加给viewpager
container.addView(imageView);
System.out.println("初始化条目:" + position);
//返回布局对象
return imageView;
}
//销毁布局对象
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
//删掉,底层扔了异常
//super.destroyItem(container, position, object);
container.removeView((ImageView) object);
System.out.println("销毁条目:" + position);
}
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="180dp">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="wrap_content"
android:layout_height="180dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#a000"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="标题" />
<LinearLayout
android:id="@+id/ll_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
</FrameLayout>
</LinearLayout>
13.下拉框效果实现
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<RelativeLayout
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<EditText
android:id="@+id/et_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/iv_drop"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/down_arrow"
android:layout_height="wrap_content" />
</RelativeLayout>
</RelativeLayout>
private ListView listView = new ListView(this);
private EditText etText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etText = findViewById(R.id.et_text);
findViewById(R.id.iv_drop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showPopup();
}
});
}
private void showPopup() {
listView.setBackgroundResource(R.drawable.listview_background);
PopupWindow popupWindow = new PopupWindow(listView, etText.getWidth(), 200, true);
popupWindow.showAsDropDown(etText, 0, 0);
}
自定义控件切换按钮
package cn.itcast.switch11;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
/**
* 控件绘制流程:
* <p>
* 1. measure方法来确定控件尺寸
* 2. layout方法确定控件位置
* 3. draw方法绘制控件内容
* <p>
* measure->layout->draw
* onMeasure->onLayout->onDraw
*
* 1280x720 xhdpi
* 480x800 hdpi
*/
public class MySwitch extends View {
private Paint paint;
private Bitmap mBitmapBg;
private Bitmap mBitmapSlide;
private int MAX_LEFT;//最大左边距
private int mSlideLeft;//当前左边距
private boolean isOpen = false;//当前开关状态
public MySwitch(Context context) {
this(context, null);
}
public MySwitch(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public MySwitch(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paint = new Paint();
paint.setColor(Color.RED);
//初始化背景图片
mBitmapBg = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);
//滑块图片
mBitmapSlide = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);
MAX_LEFT = mBitmapBg.getWidth() - mBitmapSlide.getWidth();
//设置点击事件
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(isOpen) {
mSlideLeft = 0;
isOpen = false;
}else {
mSlideLeft = MAX_LEFT;
isOpen = true;
}
//刷新当前控件
invalidate();//此方法会导致onDraw重新走一遍
}
});
}
//重写此方法可以修改控件尺寸
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//setMeasuredDimension(100, 100);
setMeasuredDimension(mBitmapBg.getWidth(), mBitmapBg.getHeight());
System.out.println("onMeasure....");
}
//设置控件位置
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
System.out.println("onLayout....");
}
//绘制控件
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//canvas.drawRect(0, 0, 200, 200, paint);
System.out.println("onDraw......");
//在左上角绘制图片
canvas.drawBitmap(mBitmapBg, 0, 0, null);
canvas.drawBitmap(mBitmapSlide, mSlideLeft, 0, null);
}
}
自定义SeekBar
mClipPath.addRoundRect
https://blog.csdn.net/weixin_34130389/article/details/91397621
ValueAnimator.ofInt
https://blog.csdn.net/songkai0825/article/details/89367666
定时器
https://www.oschina.net/question/2447911_2176528
xml一半圆角
https://blog.csdn.net/jdsjlzx/article/details/46989023
float[] radii={12f,12f,0f,0f,0f,0f,0f,0f};
path.addRoundRect(new RectF(0, 0, 50, 50), radii, Path.Direction.CW);canvas.drawPath(path,paint);
自定义seekbar
https://github.com/525642022/MyCustomSeekBar
https://github.com/zhangliangming/SeekBar/blob/master/seekbarlibrary/src/main/java/com/zlm/libs/widget/CustomSeekBar.java