Android learning notes - Material style

Material style

01 slide menu

1 DrawerLayout

  drawerLayout is a layout container There are two child controls inside, the first is the main screen control, and the second is the sliding menu The second control must specify layout_gravity

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 <!-- First control-->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            />
    </FrameLayout>
    <!--Second control,Menu slide direction,layout_gravity-->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:text="this is menu"
        android:textSize="30sp"
        android:background="#FFF"/>

</androidx.drawerlayout.widget.DrawerLayout>

   when sliding, it may conflict with the mobile phone gesture. In this case, you can turn off the gesture and use navigation Or start the navigation button of the actionbar

mainactivity.java

public class MainActivity extends AppCompatActivity {

    private DrawerLayout mDrawerLayout ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Set toolbar to actionbar. Note that Android X appcompat. widget. Toolbar package; Otherwise, the parameters of the setSupportActionBar method will be incorrect
        Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar !=null){
            //Show navigation buttons
            actionBar.setDisplayHomeAsUpEnabled(true);
            //Set the navigation icon, using the vector icon in studio
            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
        }
    }

    //Process navigation buttons
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                mDrawerLayout.openDrawer(GravityCompat.START); //start is consistent with that in xml
                break;
        }
        return true;
    }
}

2 NavigationView

Import dependency

implementation 'com.google.android.material:material:1.1.0'
implementation 'de.hdodenhof:circleimageview:3.0.1'

Prepare menu and headerLayout in NavigationView

Menu file nav_menu.xml

  create a new menu directory under the res directory, new - > menu resource file

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- single Menu items can only be selected by radio   -->
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/navCall"
            android:icon="@drawable/ic_call"
            android:title="Call" />
        <item
            android:id="@+id/navFriends"
            android:icon="@drawable/ic_friend"
            android:title="Friends" />
        <item
            android:id="@+id/navLocation"
            android:icon="@drawable/ic_location"
            android:title="Location" />

    </group>
</menu>

New nav_header.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:padding="10dp"
    android:background="?attr/colorPrimary"
    >
    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/icon_image"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:src="@drawable/ic_image"
        android:layout_centerInParent="true"/>
    <TextView
        android:id="@+id/username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Tony"
        android:textColor="#FFF"
        android:layout_above="@+id/mail"
        android:textSize="14sp"/>
    <TextView
        android:id="@+id/mail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:layout_alignParentBottom="true"
        android:text="123456@qq.com"
        android:textColor="#FFF"
        android:textSize="14sp"/>
</RelativeLayout>

In activity_ Add in main

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/nav_menu"
        app:headerLayout="@layout/nav_header"/>

Add code in MainActivity

//2 menu
NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
//Set default selected item
navView.setCheckedItem(R.id.navCall);
//Set the listener when item is selected
navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        mDrawerLayout.closeDrawers();
        return true;
    }
});

02 hover button and interactive prompt

1 suspension button

add button

<!-- elevation Is height,The higher the height,The lighter the shadow,The wider the projection range-->
<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fabtn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="16dp"
    android:src= "@drawable/ic_done"
    android:elevation="3dp"
    />

Click events can be set

//3 suspension button click event
FloatingActionButton fabtn = (FloatingActionButton) findViewById(R.id.fabtn);
fabtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this,"Fabtn clicked",Toast.LENGTH_SHORT).show();
    }
});

2 Snackbar

It is an extension of Toast (not a substitute. Both have their own applicable scenarios) to realize the revocation action

Snackbar.make(v,"Data deleted",Snackbar.LENGTH_SHORT)
        .setAction("Undo",new View.OnClickListener(){ //
            @Override
            //Click Cancel
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"Data restored",Toast.LENGTH_SHORT).show();
            }
        })
        .show();

3 coordinatorlayout (enhanced framelayout)

   the button will be blocked after the above undo action appears. In order to cancel this phenomenon, the enhanced frameLayout is applicable. This layout can listen to various events of all child controls and automatically make reasonable responses

<androidx.coordinatorlayout.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    </androidx.coordinatorlayout.widget.CoordinatorLayout>

03 card layout

1 layout CardView

recyclerView and glide libraries are used

Import dependency

implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.9.0'

Use recyclerView to display pictures in enhanced frameout (non sliding menu)

The item in the recyclerView uses a card layout (a bit like a floating button)

recyclerView component added (in activity_main)

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

recyclerView item file fruit_item

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_margin="5dp"
    app:cardCornerRadius="4dp">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <!--picture-->
        <ImageView
            android:id="@+id/fruit_image"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:scaleType="centerCrop"/>
         <!--written words-->
        <TextView
            android:id="@+id/fruit_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_margin="5dp"
            android:textSize="16sp"/>
    </LinearLayout>

</androidx.cardview.widget.CardView>

recyclerView custom adapter

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.MyViewHolder> {

    //item data
    private List<Fruit> data;
    private Context context;

    public FruitAdapter(List<Fruit> data, Context context) {
        this.data = data;
        this.context = context;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //1. Get item layout style
        View view = View.inflate(context, R.layout.fruit_item,null);
        //3. Return to textView in item layout
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        //4. Bind data for item
        Fruit fruit = data.get(position);
        holder.fruitName.setText(fruit.getName());
        //Bind an image to the imageView component according to the ImageID (which can be an image address) in the fruit object
        Glide.with(context).load(fruit.getImageId()).into(holder.fruitImage);
    }

    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder{
        //2. Get the textView in the layout item style
        private CardView cardView;
        private ImageView fruitImage;
        TextView fruitName;
        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            //2.
            cardView = (CardView) itemView;
            fruitImage = (ImageView) cardView.findViewById(R.id.fruit_image);
            fruitName = (TextView) cardView.findViewById(R.id.fruit_name);
        }
    }
}

Data entity

public class Fruit {
    private String name;
    private int imageId;
	//get\ set \constructor
}

Render recyclerView in mainactivity

//4_ 1 card layout, fruit data
private Fruit[] fruits = {new Fruit("Apple",R.drawable.fruit_1),new Fruit("Banana",R.drawable.fruit_2)};
private List<Fruit> fruitList = new ArrayList<>();
private FruitAdapter adapter;
//4_ 2 card layout rendering recyclerView
initFruits();
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
GridLayoutManager layoutManager = new GridLayoutManager(this,2);
recyclerView.setLayoutManager(layoutManager);
adapter = new FruitAdapter(fruitList,this);
recyclerView.setAdapter(adapter);

//4_ 3 assign a value to the fruit array
private void initFruits() {
    fruitList.clear();
    for (int i = 0; i < 50; i++) {
        Random random = new Random();
        int index = random.nextInt(fruits.length);
        fruitList.add(fruits[index]);
    }
}

result:

2 appbarlayout (linear layout in vertical direction)

  as can be seen from the above figure, the toolbar is blocked in the coordinator layout

   CoordinatorLayout is an enhanced version of FrameLayout. Without explicit positioning, all controls in FrameLayout will be placed in the upper left corner of the layout by default, resulting in occlusion.

  solution:

Place the toolbar in appbarlayout

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:layout_scrollFlags="scroll|enterAlways|snap"
        />
</com.google.android.material.appbar.AppBarLayout>

Add behavior for toolbar and recyclerView

<!--toolbar-->
<!--
scroll Mean when RecyclerView When scrolling up,Toolbar Will scroll up and hide together;
enterAlways Mean when RecyclerView When scrolling down,Toolbar It scrolls down and redisplays;
snap Mean when Toolbar Not completely hidden or displayed,Scrolls according to the current distance,Automatically select whether to hide or show.-->
app:layout_scrollFlags="scroll|enterAlways|snap"
<!--recyclerView-->
app:layout_behavior="@string/appbar_scrolling_view_behavior"

04 drop down refresh (SwipeRefreshLayout)

  add dependency

implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"

recyclerView supports drop-down refresh and puts recyclerView into the SwipeRefreshLayout layout

<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
    android:id="@+id/swipe_refresh"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    >
    <!--        Card layout-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
//5_ 1 pull down refresh
swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
//Drop down refresh progress bar color
swipeRefresh.setColorSchemeResources(R.color.design_default_color_primary);
//5_ 2 pull down trigger event
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
        refreshFruits();
    }
});
//5_ 3 pull down refresh fruit
private void refreshFruits() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    initFruits();
                    adapter.notifyDataSetChanged();
                    swipeRefresh.setRefreshing(false);
                }
            });
        }
    }).start();
}

05 collapsing toolbar layout

  CollapsingToolbarLayout depends on appbarlayout, and appbarlayout depends on CoordinatorLayout

Next, the foldable title block will be used on the fruit details page

effect:

The structure of the details page is as follows

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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=".FruitActivity">
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="250dp">
        <!--  Collapsible title block      -->
        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">
            <!--theme Specify theme,contentScrim Specifies the background color that tends to or after the collapsed state
                        app:layout_scrollFlags attribute
                        among,scroll express CollapsingToolbarLayout It will scroll with the details of the fruit content,
                        exitUntilCollapsed Mean when CollapsingToolbarLayout With scrolling, it remains on the interface after folding,Don't move out of the screen again.-->
            <!-- collapseMode
            Used to specify where the current control is located CollapsingToolbarLayout Folding mode during folding,
            among Toolbar Designated as pin,Indicates that the position remains unchanged during folding,
            ImageView Designated as parallax,Indicates that a certain dislocation offset will occur during the folding process,
            The visual effect of this mode will be very good.           -->
            <ImageView
                android:id="@+id/fruit_image_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"/>
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"/>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>
    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="15dp"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_marginTop="35dp"
                app:cardCornerRadius="4dp">
                <TextView
                    android:id="@+id/fruit_content_text"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp"/>
            </androidx.cardview.widget.CardView>
        </LinearLayout>
    </androidx.core.widget.NestedScrollView>
    <!--  Suspension button anchor settings anchor  -->
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:src="@drawable/ic_comment"
        app:layout_anchor="@id/appBar"
        app:layout_anchorGravity="bottom|end"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

CoordinatorLayout

  appbarlayout (collapsible title block)

     collapsing toolbar layout (collapsible title bar)

       ImageView (put pictures)

       toolbar (general title bar)

   nestedscrollview (used to describe fruit)

  floatactionbutton

Fruit details page activity java

//Note the package imported by toolbar
public class FruitActivity extends AppCompatActivity {

    public static final String FRUIT_NAME = "fruit_name";
    public static final String FRUIT_IMAGE_ID = "fruit_image_id";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fruit);

        //1 get the information of jump page
        Intent intent = getIntent();
        String fruitName = intent.getStringExtra(FRUIT_NAME);
        int fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID,0);

        //Collapsible title block
        CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        //toolbar and pictures
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        ImageView fruitImageView = (ImageView) findViewById(R.id.fruit_image_view);
        //Content details
        TextView fruitContentText = (TextView) findViewById(R.id.fruit_content_text);

        //Set toolbar to actionbar
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar!=null){
            actionBar.setDisplayHomeAsUpEnabled(true);  //Set navigation mark
        }
        //Set the title for the collapsible title block
        collapsingToolbar.setTitle(fruitName);
        //Set picture
        Glide.with(this).load(fruitImageId).into(fruitImageView);
        String fruitContent = generateFruitContent(fruitName);
        fruitContentText.setText(fruitContent);
    }

    //Automatically generate content details
    private String generateFruitContent(String fruitName) {
        StringBuilder fruitContent = new StringBuilder();
        for (int i = 0; i < 500; i++) {
            fruitContent.append(fruitName);
        }
        return fruitContent.toString();
    }

    //
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        //Handling navigation bar HomeAsUp events
        switch (item.getItemId()){
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Set adapter click event

//In the ViewHolder constructor, specify ronghe
//Click event
itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        int positon =  getAdapterPosition();
        Fruit fruit = data.get(positon);
        Intent intent = new Intent(context, FruitActivity.class);
        intent.putExtra(FruitActivity.FRUIT_NAME,fruit.getName());
        intent.putExtra(FruitActivity.FRUIT_IMAGE_ID,fruit.getImageId());
        context.startActivity(intent);
    }
});
    //Set click event
    //----------------------------------------------------------------------------
    private OnRecyclerItemClickListener mOnItemClickListener;

    //2_ 1 generate listener
    public void setmOnItemClickListener(OnRecyclerItemClickListener mOnItemClickListener) {
        this.mOnItemClickListener = mOnItemClickListener;
    }
    //Interface
    public interface OnRecyclerItemClickListener{
        void onRecyclerItemClick(int position);
    }

1. Perfection – integration of system status bar control and background drawing

System status bar - the line where the power is

Add properties for the control to be merged and its parent layout

android:fitsSystemWindows="true"

In res - > values - > themes XML add

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.MyApplication" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>
	<!--Inherit the above style-->
    <style name="FruitActivityTheme" parent="Theme.MyApplication">
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

At manifest Add the following topics to the fruitActivity in XML

android:theme="@style/FruitActivityTheme"

effect:

The system bar and picture are integrated

Keywords: Android

Added by stitchmedia on Mon, 27 Dec 2021 17:57:43 +0200