Android Carousel adapter Demo 笔记

628 阅读1分钟

wiki

源码: github.com/androidx/co… 摘录部分代码块:

dependencies {
        implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
    } 

获取系统所有xml 文件名:

private static String[] getLayouts(Test filter) {
        ArrayList<String> list = new ArrayList<>();
        Field[] f = R.layout.class.getDeclaredFields();

        Arrays.sort(f, (f1, f2) -> {
            int v = (REVERSE ? -1 : 1) * f1.getName().compareTo(f2.getName());
            if (SHOW_FIRST == null) {
                return v;
            }
            if (f1.getName().matches(SHOW_FIRST)) {
                return -1;
            }
            if (f2.getName().matches(SHOW_FIRST)) {
                return +1;
            }
            return v;
        });
        for (int i = 0; i < f.length; i++) {
            String name = f[i].getName();
            if (filter == null || filter.test(name)) {
                list.add(name);
            }
        }
        return list.toArray(new String[0]);
    }

拿到所有demo的xml文件之后,可以动态设置setContentView,实现一个activity 运行多个布局

    private void setupActivity(Bundle extra) {
        //layout name
        String prelayout = extra.getString(Loader.KEY);
        layout_name = prelayout;
        Context ctx = getApplicationContext();
        //layout id
        int id = ctx.getResources().getIdentifier(prelayout, "layout", ctx.getPackageName());
        //设置全屏模式
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        ActionBar bar = getSupportActionBar();
        if (bar != null) {
            bar.hide();
        }
        //设置内容布局
        setContentView(id);
        ActionBar actionBar = getSupportActionBar();
        actionBar.setBackgroundDrawable(new ColorDrawable(0xFFfd401d));

        ViewGroup root = ((ViewGroup) findViewById(android.R.id.content).getRootView());
        View mlView = findViewById(R.id.motionLayout);
        mMotionLayout = (mlView != null) ? (MotionLayout) mlView : Loader.findMotionLayout(root);
    } 

旋转视图: 在这里插入图片描述

//Setup the Carousel adapter

  /**
     * Adapter for a Carousel
     */
    public interface Adapter {
        /**
         * Number of items you want to display in the Carousel
         * @return number of items 总数
         */
        int count();

        /**
         * Callback to populate the view for the given index
         * 相当于getview
         * @param view
         * @param index
         */
        void populate(View view, int index);

        /**
         * Callback when we reach a new index
         * @param index
         */
        void onNewItem(int index);
    }

MotionLayout 仅适用于其直接子级,不支持嵌套布局层次结构或 Activity 转换、

app:layoutDescription 引用的是MotionScene 包含布局的运动描述,

developer.android.google.cn/training/co… MotionLayout 属性 app:showPaths="boolean" 表示在运动进行时是否显示运动路径 app:motionDebug="SHOW_ALL" 显示与运动有关的其他调试信息

demo_010_carousel.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout 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"
    android:id="@+id/motionLayout"
    app:showPaths="true"
    app:layoutDescription="@xml/demo_010_carousel_scene">

    <ImageView
        android:id="@+id/imageView0"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginEnd="16dp"
        android:scaleType="centerCrop"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/imageView1"
        app:layout_constraintTop_toTopOf="parent"
        android:src="@drawable/goldengate" />

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginEnd="16dp"
        android:scaleType="centerCrop"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/imageView2"
        app:layout_constraintTop_toTopOf="parent"
        android:src="@drawable/bryce_canyon" />

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:scaleType="centerCrop"
        android:src="@drawable/fitzgerald_marine_reserve"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/imageView3"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginStart="16dp"
        android:scaleType="centerCrop"
        android:src="@drawable/death_valley"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/imageView2"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/imageView4"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginStart="16dp"
        android:scaleType="centerCrop"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/imageView3"
        app:layout_constraintTop_toTopOf="parent"
        android:src="@drawable/goldengate" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="100dp" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_end="100dp" />

    <androidx.constraintlayout.helper.widget.Carousel
        android:id="@+id/carousel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:carousel_forwardTransition="@+id/forward"
        app:carousel_backwardTransition="@+id/backward"
        app:carousel_previousState="@+id/previous"
        app:carousel_nextState="@+id/next"
        app:carousel_infinite="true"
        app:carousel_firstView="@+id/imageView2"
        app:constraint_referenced_ids="imageView0,imageView1,imageView2,imageView3,imageView4" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="36dp"
        android:text="go to last item"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.motion.widget.MotionLayout>

对应的需要layoutDescription, demo_010_carousel_scene.xml

<?xml version="1.0" encoding="utf-8"?>
<MotionScene 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        motion:constraintSetStart="@id/start"
        motion:constraintSetEnd="@+id/next"
        motion:duration="1000"
        android:id="@+id/forward">
        <KeyFrameSet>
        </KeyFrameSet>
        <OnSwipe
            motion:dragDirection="dragLeft"
            motion:touchAnchorSide="left" />
    </Transition>

    <Transition
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/previous"
        android:id="@+id/backward">

        <OnSwipe
            motion:dragDirection="dragRight"
            motion:touchAnchorSide="right" />

    </Transition>


    <ConstraintSet android:id="@+id/previous">
        <Constraint
            android:layout_width="100dp"
            android:layout_height="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintStart_toStartOf="@id/guideline2"
            android:id="@+id/imageView2"
            android:layout_marginTop="16dp"
            android:layout_marginBottom="16dp"
            android:layout_marginStart="16dp" />
        <Constraint
            android:id="@+id/imageView3"
            motion:layout_constraintStart_toEndOf="@+id/imageView2"
            android:layout_width="100dp"
            android:layout_height="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            android:layout_marginStart="16dp" />
        <Constraint
            android:id="@+id/imageView1"
            motion:layout_constraintEnd_toStartOf="@id/guideline2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginEnd="16dp"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintStart_toEndOf="@id/guideline"
            motion:layout_constraintDimensionRatio="1:1"
            android:layout_marginTop="16dp"
            android:layout_marginBottom="16dp"
            android:layout_marginStart="16dp" />
        <Constraint
            android:id="@+id/imageView0"
            motion:layout_constraintEnd_toStartOf="@id/guideline"
            android:layout_width="100dp"
            android:layout_height="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginEnd="16dp"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/start">
        <Constraint
            motion:layout_constraintEnd_toEndOf="@id/guideline2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintHorizontal_bias="0.5"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintStart_toStartOf="@id/guideline"
            android:id="@+id/imageView2"
            motion:layout_constraintDimensionRatio="w,1:1"
            android:layout_marginTop="16dp"
            android:layout_marginBottom="16dp"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:layout_marginLeft="16dp"
            android:layout_marginStart="16dp" />
        <Constraint
            android:id="@+id/imageView3"
            motion:layout_constraintStart_toEndOf="@id/guideline2"
            android:layout_width="100dp"
            android:layout_height="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginStart="16dp"
            motion:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@+id/imageView1"
            motion:layout_constraintEnd_toStartOf="@id/guideline"
            android:layout_width="100dp"
            android:layout_height="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginEnd="16dp"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/next">
        <Constraint
            android:layout_width="100dp"
            android:layout_height="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            android:id="@+id/imageView2"
            motion:layout_constraintEnd_toStartOf="@id/guideline"
            android:layout_marginRight="16dp"
            android:layout_marginEnd="16dp" />
        <Constraint
            android:id="@+id/imageView3"
            motion:layout_constraintStart_toEndOf="@id/guideline"
            android:layout_width="0dp"
            android:layout_height="0dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginStart="16dp"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintEnd_toStartOf="@id/guideline2"
            android:layout_marginEnd="16dp"
            motion:layout_constraintDimensionRatio="1:1"
            android:layout_marginTop="16dp"
            android:layout_marginBottom="16dp" />
        <Constraint
            android:id="@+id/imageView4"
            motion:layout_constraintStart_toEndOf="@id/guideline2"
            android:layout_width="100dp"
            android:layout_height="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginStart="16dp"
            motion:layout_constraintTop_toTopOf="parent"
            android:layout_marginLeft="16dp" />
    </ConstraintSet>

</MotionScene>

CircularFlow 环形布局 在这里插入图片描述

activity_circular_flow_demo.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".CircularFlowDemoActivity">

    <View
        android:id="@+id/view1"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@android:color/black"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/view2"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:background="@android:color/darker_gray" />

    <View
        android:id="@+id/view3"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:background="@android:color/holo_red_dark" />

    <View
        android:id="@+id/view4"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:background="@android:color/holo_green_dark" />


    <View
        android:id="@+id/view5"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:background="@android:color/holo_blue_dark" />


    <View
        android:id="@+id/view6"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="16dp"
        android:background="@android:color/holo_orange_dark"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <View
        android:id="@+id/view7"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:background="@android:color/holo_purple"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/view8"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:background="@android:color/holo_green_light"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/view9"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="136dp"
        android:background="@android:color/holo_green_light"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/view10"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:layout_marginTop="116dp"
        android:layout_marginEnd="116dp"
        android:background="@android:color/holo_green_light"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/view11"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:layout_marginTop="116dp"
        android:layout_marginEnd="216dp"
        android:background="@android:color/holo_green_light"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/view12"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:layout_marginTop="161dp"
        android:layout_marginEnd="216dp"
        android:background="@android:color/holo_green_light"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <View
        android:id="@+id/view13"
        android:layout_width="50dp"
        android:layout_height="10dp"
        android:layout_marginTop="161dp"
        android:layout_marginEnd="416dp"
        android:background="@android:color/holo_red_dark"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.helper.widget.CircularFlow
        android:id="@+id/circularFlow"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:circularflow_angles="10, 40, 80, 135"
        app:circularflow_defaultAngle="45"
        app:circularflow_defaultRadius="10dp"
        app:circularflow_radiusInDP="110, 150, 170, 190"
        app:circularflow_viewCenter="@+id/view1"
        app:constraint_referenced_ids="view13,view2,view3,view4,view5,view6,view7,view8,view9,view10,view11,view12" />
</androidx.constraintlayout.widget.ConstraintLayout>

CircularFlowDemoActivity.kt

package androidx.constraintlayout.experiments

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.helper.widget.CircularFlow

class CircularFlowDemoActivity : AppCompatActivity() {
    var views = intArrayOf(
        R.id.view2,
        R.id.view3,
        R.id.view4,
        R.id.view5,
        R.id.view6,
        R.id.view7,
        R.id.view8,
        R.id.view9,
        R.id.view10,
        R.id.view11,
        R.id.view12,
        R.id.view13
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_circular_flow_demo)

        val circularFlow = findViewById<CircularFlow>(R.id.circularFlow)

        findViewById<View>(R.id.view1).setOnClickListener {

            views.indices.forEach { i ->
                val view = findViewById<View>(views[i])
                circularFlow.updateReference(view, 120, i * 30f)
                view.rotation = 90 - (360 - i * 30f)
            }


        }


    }
}