天天看點

自定義veiw

ViewPager

一篇中簡單使用了原點訓示器,這裡來仿寫一個。使用自定義控件的方式來進行。然後使用

attrs.xml

聲明的方式來進行,即(主布局檔案):

<?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=".LunchIndicatorActivity">

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/indicatorViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <com.example.mylunch.MyIndicator
        android:id="@+id/my_indicator"
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="50dp"
        app:Indicator_number="3"
        app:Indicator_offset="0"
        app:Indicator_radius="10"
        app:Indicator_strokeWidth="2" />
</RelativeLayout>
           

首先定義自己的訓示器的

view

對象,即

MyIndicator

,如下:

public class MyIndicator extends View {

    private Paint paint = new Paint();
    private Paint curPaint = new Paint();
    private int number = 4;
    private int radius = 20;
    private float offset = 2;
    private int strokeWidth = 2;

    public void setOffset(int position, float positionOffset){
        this.offset = position + positionOffset;
        // 重新繪制
        invalidate();
    }

    private void initPaint(){
        paint.setStrokeWidth(strokeWidth);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.rgb(23, 234, 120));

        curPaint.setStrokeWidth(strokeWidth);
        curPaint.setAntiAlias(true);
        curPaint.setStyle(Paint.Style.FILL);
        curPaint.setColor(Color.RED);
    }

    public MyIndicator(Context context) {
        super(context);
    }

    public MyIndicator(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyIndicator);
        number = array.getInt(R.styleable.MyIndicator_Indicator_number, number);  // 擷取值,沒有就設定預設值4
        radius = array.getInt(R.styleable.MyIndicator_Indicator_radius, radius);
        strokeWidth = array.getInt(R.styleable.MyIndicator_Indicator_strokeWidth, strokeWidth);
        offset = array.getFloat(R.styleable.MyIndicator_Indicator_offset, offset);

        initPaint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for(int i=0;i<number;i++){
            canvas.drawCircle(50 + i * 3 * radius, 20, radius - strokeWidth / 2, paint);
        }
        canvas.drawCircle( 50 + offset * 3 * radius, 20, radius, curPaint);
    }
}
           

在構造器中的

TypedArray

部分,也就是加載在

xml

檔案中自定義的一下屬性,即這個部分:

app:Indicator_number="3"
app:Indicator_offset="0"
app:Indicator_radius="10"
app:Indicator_strokeWidth="2"
           

那麼,這個自定義的和

View

相關的屬性是怎麼做關聯的呢,來自于

attrs.xml

檔案中的聲明,即:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyIndicator">
        <attr name="Indicator_number" format="integer"></attr>
        <attr name="Indicator_radius" format="integer"></attr>
        <attr name="Indicator_offset" format="float"></attr>
        <attr name="Indicator_strokeWidth" format="integer"></attr>
    </declare-styleable>
</resources>
           

最終在

Activity

中的使用就和之前的一樣,即:

public class LunchIndicatorActivity extends AppCompatActivity {

    private ViewPager viewPager;
    private int[] datas = {
      R.drawable.tu_1,
      R.drawable.tu_2,
      R.drawable.tu_3
    };
    private List<View> views = new ArrayList<>();
    private MyIndicator indicator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lunch_indicator);
        viewPager = findViewById(R.id.indicatorViewPager);
        indicator = findViewById(R.id.my_indicator);
        initData();
        viewPager.setAdapter(new MyViewPagerAdapter());
        viewPager.setOnPageChangeListener(new MyViewPagerListener());
    }

    class MyViewPagerListener implements ViewPager.OnPageChangeListener{
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            indicator.setOffset(position, positionOffset);
        }
        @Override
        public void onPageSelected(int position) {}
        @Override
        public void onPageScrollStateChanged(int state) {}
    }

    private void initData(){
        for(int i=0;i<datas.length;i++){
            View view = getLayoutInflater().inflate(R.layout.view_pager_item, null);
            ImageView imageView = view.findViewById(R.id.imageveiw);
            imageView.setImageResource(datas[i]);
            views.add(view);
        }
    }

    class MyViewPagerAdapter extends PagerAdapter{
        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            View view = views.get(position);
            container.addView(view);
            return view;
        }
        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            container.removeView(views.get(position));
        }
        @Override
        public int getCount() {
            return datas.length;
        }
        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
            return view==object;
        }
    }
}
           

最終就可以達到一個連環的訓示器滑動的效果。

繼續閱讀