آموزش Recyclerview و Cardview در اندروید

یکی از عناصر اصلی در  طراحی متریال دیزاین  ، Cardview می باشد. با استفاده از کارد ویو شما می توانید اطلاعات را در کارت با سایه های روبه پایین و گوشه های شعاع دار که با سایر پلت فرم ها سازگار می باشد، قرار دهید. Cardview  گسترش یافته ی FrameLayout می باشد. در ادامه با آموزش Recyclerview و Cardview در اندروید با آموزشگاه های برنامه نویسی در مشهد همراه باشید.

هنگامی که Cardview با RecyclerView ترکیب شوند، در نهایت خروجی بسیار زیبا برای UI را به همراه خواهد داشت. در این مطلب قصد داریم نحوه ی ادغام CardView و RecyclerView را برای ایجاد یک برنامه ی موسیقی زیبا که آلبوم های موسیقی را با تصویر و عنوان نمایش میدهد را آموزش دهیم.

اضافه کردن CardView

برای استفاده از CardView در برنامه ی خود در مرحله ی اول باید بتوانید موارد وابسته به CardView را در build.grade  اضافه و پروژه را sync کنید.

build.gradle
dependencies {
    // CardView
    compile 'com.android.support:cardview-v7:23.3.+'
}

 

ویجت <android.support.v7.widget.CardView> را به لایه های خود اضافه کنید و سایر ویجت های UI مانند ImageView و TextView را در داخل آن قرار دهید. در Cardview زیر کاملا مشخص است که تنها یک  TextView در آن قرار گرفته شده است.

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:card_view="http://schemas.android.com/apk/res-auto">

    <android.support.v7.widget.CardView
        xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/card_view"
        android:layout_gravity="center"
        android:layout_width="250dp"
        android:layout_height="250dp"
        card_view:cardCornerRadius="4dp">

        <TextView
            android:text="Hello Card"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </android.support.v7.widget.CardView>

</LinearLayout>

بعد از انجام این مراحل، کار را برای ایجاد پروژه ی جدید ادامه خواهیم داد.

ایجاد پروژه ی جدید

  1. یک پروژه ی جدید را در اندروید استودیو از منوی file/new project ایجاد کنید. در این مرحله اگر از شما درخواست شد تا فعالیت پیش فرض را انتخاب کنید، Empty Activity را انتخاب و ادامه دهید.
  2. فایل res.zip را دانلود و به پوشه ی پروژه ی خود اضافه کنید. این پوشه شامل چند آلبوم و آیکن های مورد نیاز برای این پروژه می باشد.
  3. رشته ها ی زیر را  که شامل رنگ ، ابعاد و منابع dimen می شوند را به فایل های string.xml, color.xml و dimen.xml اضافه کنید.
strings.xml
<resources>
    <string name="app_name">Card View</string>
    <string name="action_settings">Settings</string>
    <string name="action_add_favourite">Add to Favourites</string>
    <string name="action_play_next">Play Next</string>
    <string name="backdrop_title">LOVE MUSIC</string>
    <string name="backdrop_subtitle">This season top 20 albums</string>
</resources>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#F50057</color>
    <color name="colorPrimaryDark">#F50057</color>
    <color name="colorAccent">#FF4081</color>
    <color name="viewBg">#f1f5f8</color>
    <color name="album_title">#4c4c4c</color>
</resources>
dimens.xml
<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="fab_margin">16dp</dimen>
    <dimen name="item_offset">10dp</dimen>
    <dimen name="detail_backdrop_height">250dp</dimen>
    <dimen name="backdrop_title">30dp</dimen>
    <dimen name="backdrop_subtitle">18dp</dimen>
    <dimen name="card_margin">5dp</dimen>
    <dimen name="card_album_radius">0dp</dimen>
    <dimen name="album_cover_height">160dp</dimen>
    <dimen name="album_title_padding">10dp</dimen>
    <dimen name="album_title">15dp</dimen>
    <dimen name="songs_count_padding_bottom">5dp</dimen>
    <dimen name="songs_count">12dp</dimen>
    <dimen name="ic_album_overflow_width">20dp</dimen>
    <dimen name="ic_album_overflow_height">30dp</dimen>
    <dimen name="ic_album_overflow_margin_top">10dp</dimen>
</resources>

۴ . build.gradle را باز و وابستگی های CardView, RecycleView و Glide را اضافه کنید.  RecycleView  برای نمایش آلبوم به صورت شبکه ای استفاده می شود. CardView برای نمایش یک مورد از آیتم آلبوم به کار برده میشود. Glide برای نمایش تصویر کاور آلبوم مورد استفاده قرار میگیرد.

build.gradle
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:design:23.3.0'
 
    // RecyclerView
    compile 'com.android.support:recyclerview-v7:23.3.+'
 
    // CardView
    compile 'com.android.support:cardview-v7:23.3.+'
 
    // Glide
    compile 'com.github.bumptech.glide:glide:3.7.0'
}

 

۵ . برای ایجاد یک آلبوم واحد، ما به یک کلاس مدل نیاز داریم تا ویژگی های آلبوم مانند نام، تعداد آهنگ ها و تصویر کاور را نشان دهد. بنابراین یک کلاس به نام Album.java را ایجاد و کد زیر را اضافه کنید.

 

Album.java
package info.androidhive.cardview;
 
/**
 * Created by Lincoln on 18/05/16.
 */
public class Album {
    private String name;
    private int numOfSongs;
    private int thumbnail;
 
    public Album() {
    }
 
    public Album(String name, int numOfSongs, int thumbnail) {
        this.name = name;
        this.numOfSongs = numOfSongs;
        this.thumbnail = thumbnail;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getNumOfSongs() {
        return numOfSongs;
    }
 
    public void setNumOfSongs(int numOfSongs) {
        this.numOfSongs = numOfSongs;
    }
 
    public int getThumbnail() {
        return thumbnail;
    }
 
    public void setThumbnail(int thumbnail) {
        this.thumbnail = thumbnail;
    }
}

 

۶ . برای نمایش کارت آلبوم به یک لایه ی xml نیاز داریم. یک لایه ی xml به نام album_card.xml زیر لایه ی res ایجاد کنید. در قطعه کد زیر متوجه میشوید که <android.support.v7.widget.CardView> را اضافه کرده ایم و تمام ویژگی های آلبوم مانند نام، تعداد آهنگ ها و همچنین تصویر کاور آلبوم اضافه شده اند. علاوه براین، یک آیتم ۳ نقطه هم برای باز شدن منوی popup برای ضربه زدن روی آن اضافه کرده ایم.

 

album_card.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
 
    <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_margin="@dimen/card_margin"
        android:elevation="3dp"
        card_view:cardCornerRadius="@dimen/card_album_radius">
 
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
 
            <ImageView
                android:id="@+id/thumbnail"
                android:layout_width="match_parent"
                android:layout_height="@dimen/album_cover_height"
                android:background="?attr/selectableItemBackgroundBorderless"
                android:clickable="true"
                android:scaleType="fitXY" />
 
            <TextView
                android:id="@+id/title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/thumbnail"
                android:paddingLeft="@dimen/album_title_padding"
                android:paddingRight="@dimen/album_title_padding"
                android:paddingTop="@dimen/album_title_padding"
                android:textColor="@color/album_title"
                android:textSize="@dimen/album_title" />
 
            <TextView
                android:id="@+id/count"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/title"
                android:paddingBottom="@dimen/songs_count_padding_bottom"
                android:paddingLeft="@dimen/album_title_padding"
                android:paddingRight="@dimen/album_title_padding"
                android:textSize="@dimen/songs_count" />
 
            <ImageView
                android:id="@+id/overflow"
                android:layout_width="@dimen/ic_album_overflow_width"
                android:layout_height="@dimen/ic_album_overflow_height"
                android:layout_alignParentRight="true"
                android:layout_below="@id/thumbnail"
                android:layout_marginTop="@dimen/ic_album_overflow_margin_top"
                android:scaleType="centerCrop"
                android:src="@drawable/ic_dots" />
 
        </RelativeLayout>
 
    </android.support.v7.widget.CardView>
 
</LinearLayout>

 

۷٫ یک فایل منو به نام menu_album.xml زیر res در فولدر منو res ⇒ menu ایجاد کنید. این منو یک منوی popup برای ضربه زدن روی آیکن نقطه ای روی هر یک از آیتم های کارت آلبوم نمایش خواهد داد.

 

menu_album.xml
<menu 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">
    <item
        android:id="@+id/action_add_favourite"
        android:orderInCategory="100"
        android:title="@string/action_add_favourite" />
 
    <item
        android:id="@+id/action_play_next"
        android:orderInCategory="101"
        android:title="@string/action_play_next" />
</menu>

۸٫ برای اجرای RecyclerView، ما به یک کلاس آداپتور نیاز داریم که اطلاعات album_card.xml را با حفظ اطلاعات مناسب بارگزاری کند. یک کلاس به نام AlbumAdapter.java ایجاد و محتوای زیر را به آن اضافه کنید.

 

AlbumsAdapter.java
package info.androidhive.cardview;
 
import android.content.Context;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
 
import com.bumptech.glide.Glide;
 
import java.util.List;
 
/**
 * Created by Ravi Tamada on 18/05/16.
 */
public class AlbumsAdapter extends RecyclerView.Adapter<AlbumsAdapter.MyViewHolder> {
 
    private Context mContext;
    private List<Album> albumList;
 
    public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView title, count;
        public ImageView thumbnail, overflow;
 
        public MyViewHolder(View view) {
            super(view);
            title = (TextView) view.findViewById(R.id.title);
            count = (TextView) view.findViewById(R.id.count);
            thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
            overflow = (ImageView) view.findViewById(R.id.overflow);
        }
    }
 
 
    public AlbumsAdapter(Context mContext, List<Album> albumList) {
        this.mContext = mContext;
        this.albumList = albumList;
    }
 
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.album_card, parent, false);
 
        return new MyViewHolder(itemView);
    }
 
    @Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        Album album = albumList.get(position);
        holder.title.setText(album.getName());
        holder.count.setText(album.getNumOfSongs() + " songs");
 
        // loading album cover using Glide library
        Glide.with(mContext).load(album.getThumbnail()).into(holder.thumbnail);
 
        holder.overflow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showPopupMenu(holder.overflow);
            }
        });
    }
 
    /**
     * Showing popup menu when tapping on 3 dots
     */
    private void showPopupMenu(View view) {
        // inflate menu
        PopupMenu popup = new PopupMenu(mContext, view);
        MenuInflater inflater = popup.getMenuInflater();
        inflater.inflate(R.menu.menu_album, popup.getMenu());
        popup.setOnMenuItemClickListener(new MyMenuItemClickListener());
        popup.show();
    }
 
    /**
     * Click listener for popup menu items
     */
    class MyMenuItemClickListener implements PopupMenu.OnMenuItemClickListener {
 
        public MyMenuItemClickListener() {
        }
 
        @Override
        public boolean onMenuItemClick(MenuItem menuItem) {
            switch (menuItem.getItemId()) {
                case R.id.action_add_favourite:
                    Toast.makeText(mContext, "Add to favourite", Toast.LENGTH_SHORT).show();
                    return true;
                case R.id.action_play_next:
                    Toast.makeText(mContext, "Play next", Toast.LENGTH_SHORT).show();
                    return true;
                default:
            }
            return false;
        }
    }
 
    @Override
    public int getItemCount() {
        return albumList.size();
    }
}

 

۹٫ فایل های لایه ی activity_main.xml و content_main.xml را باز و AppBarLayout ، CollapsingToolbarLayout، Toolbar و RecyclerView را اضافه کنید.

 

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:fitsSystemWindows="true">
 
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/detail_backdrop_height"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleTextAppearance="@android:color/transparent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">
 
            <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
 
                <ImageView
                    android:id="@+id/backdrop"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:fitsSystemWindows="true"
                    android:scaleType="centerCrop"
                    app:layout_collapseMode="parallax" />
 
                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:gravity="center_horizontal"
                    android:orientation="vertical">
 
                    <TextView
                        android:id="@+id/love_music"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/backdrop_title"
                        android:textColor="@android:color/white"
                        android:textSize="@dimen/backdrop_title" />
 
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/backdrop_subtitle"
                        android:textColor="@android:color/white"
                        android:textSize="@dimen/backdrop_subtitle" />
 
                </LinearLayout>
            </RelativeLayout>
 
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
 
        </android.support.design.widget.CollapsingToolbarLayout>
 
    </android.support.design.widget.AppBarLayout>
 
    <include layout="@layout/content_main" />
 
</android.support.design.widget.CoordinatorLayout>

content_main.xml

content_main.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"
    android:background="@color/viewBg"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="info.androidhive.cardview.MainActivity"
    tools:showIn="@layout/activity_main">
 
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clipToPadding="false"
        android:scrollbars="vertical" />
 
</RelativeLayout>

 

۱۰٫ در نهایت، MainActivity.java را باز و تغییرات لازم را اعمال کنید.

()initCollapsingToolbar : عنوان تولبار را زمانی که تولبار collapsed یا expanded میشوند نمایش یا پنهان خواهد کرد.

() prepareAlbums: اطلاعات مورد نیاز آلبوم نمونه را برای RecyclerView اضافه میکند.

GridLayoutManager برای نمایش RecyclerView به حالت Grid به جای لیست استفاده میشود.

GridSpacingItemDecoration برای داشتن حاشیه های برابر اطراف آیتم شبکه ی RecyclerView استفاده میشود

AlbumsAdapter نمونه ایجاد شده را به RecyclerView اختصاص داده و آلبوم های CardView به صورت شبکه ای نمایش داده شوند.

MainActivity.java
package info.androidhive.cardview;
 
import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;
 
import com.bumptech.glide.Glide;
 
import java.util.ArrayList;
import java.util.List;
 
public class MainActivity extends AppCompatActivity {
 
    private RecyclerView recyclerView;
    private AlbumsAdapter adapter;
    private List<Album> albumList;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
 
        initCollapsingToolbar();
 
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
 
        albumList = new ArrayList<>();
        adapter = new AlbumsAdapter(this, albumList);
 
        RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2);
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), true));
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(adapter);
 
        prepareAlbums();
 
        try {
            Glide.with(this).load(R.drawable.cover).into((ImageView) findViewById(R.id.backdrop));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    /**
     * Initializing collapsing toolbar
     * Will show and hide the toolbar title on scroll
     */
    private void initCollapsingToolbar() {
        final CollapsingToolbarLayout collapsingToolbar =
                (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        collapsingToolbar.setTitle(" ");
        AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
        appBarLayout.setExpanded(true);
 
        // hiding & showing the title when toolbar expanded & collapsed
        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            boolean isShow = false;
            int scrollRange = -1;
 
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (scrollRange == -1) {
                    scrollRange = appBarLayout.getTotalScrollRange();
                }
                if (scrollRange + verticalOffset == 0) {
                    collapsingToolbar.setTitle(getString(R.string.app_name));
                    isShow = true;
                } else if (isShow) {
                    collapsingToolbar.setTitle(" ");
                    isShow = false;
                }
            }
        });
    }
 
    /**
     * Adding few albums for testing
     */
    private void prepareAlbums() {
        int[] covers = new int[]{
                R.drawable.album1,
                R.drawable.album2,
                R.drawable.album3,
                R.drawable.album4,
                R.drawable.album5,
                R.drawable.album6,
                R.drawable.album7,
                R.drawable.album8,
                R.drawable.album9,
                R.drawable.album10,
                R.drawable.album11};
 
        Album a = new Album("True Romance", 13, covers[0]);
        albumList.add(a);
 
        a = new Album("Xscpae", 8, covers[1]);
        albumList.add(a);
 
        a = new Album("Maroon 5", 11, covers[2]);
        albumList.add(a);
 
        a = new Album("Born to Die", 12, covers[3]);
        albumList.add(a);
 
        a = new Album("Honeymoon", 14, covers[4]);
        albumList.add(a);
 
        a = new Album("I Need a Doctor", 1, covers[5]);
        albumList.add(a);
 
        a = new Album("Loud", 11, covers[6]);
        albumList.add(a);
 
        a = new Album("Legend", 14, covers[7]);
        albumList.add(a);
 
        a = new Album("Hello", 11, covers[8]);
        albumList.add(a);
 
        a = new Album("Greatest Hits", 17, covers[9]);
        albumList.add(a);
 
        adapter.notifyDataSetChanged();
    }
 
    /**
     * RecyclerView item decoration - give equal margin around grid item
     */
    public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
 
        private int spanCount;
        private int spacing;
        private boolean includeEdge;
 
        public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
            this.spanCount = spanCount;
            this.spacing = spacing;
            this.includeEdge = includeEdge;
        }
 
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int position = parent.getChildAdapterPosition(view); // item position
            int column = position % spanCount; // item column
 
            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
 
                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }
        }
    }
 
    /**
     * Converting dp to pixel
     */
    private int dpToPx(int dp) {
        Resources r = getResources();
        return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
    }
}

اگر برنامه را اجرا کنید، نمایش شبکه ای CradView آلبوم را مشاهده خواهید کرد.

 

آموزش Recyclerview و Cardview در اندروید

شما می توانید برای شرکت در کلاس های برنامه نویسی در مشهد و آموزش اندروید مشهد با ما در تماس باشید

ورکشاپ رایگان دوره های تخصصی برنامه نویسی

شما این فرصت را دارید، با تکمیل فرم زیر، قبل از انتخاب دوره آموزشی مناسب خود، در ورکشاپ رایگان دوره های تخصصی برنامه نویسی شرکت کنید
  • این فیلد برای اعتبار سنجی است و باید بدون تغییر باقی بماند .

درباره‌ی محمد آذرنیوا

من محمد آذرنیوا، نویسنده و مدرس دوره های برنامه نویسی ، طراحی وب و تحلیل گر پایگاه داده هستم و قصد دارم در این وبسایت مطالب کاربردی در این زمینه را با شما به اشتراک بگذارم ...

همچنین ببینید

گزارش دوره اندروید

گزارش دوره آموزش اندروید – جلسه هشتم

جسله هشتم از دوره آموزش اندروید برگزار گردید . مهندس آذرنیوا مدرس دوره به معرفی …

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *