কার্ড স্ক্রোলার

গ্লাসের সাহায্যে, আপনি আপনার কার্ডগুলির সাথে স্ক্রলিং এবং অ্যানিমেশনের মতো সমৃদ্ধ মিথস্ক্রিয়া তৈরি করতে পারেন৷

ক্রিয়াকলাপে স্ক্রলিং কার্ড

গ্লাস ডিসপ্লে এবং টাচপ্যাড গ্লাস টাইমলাইনের মতো সোয়াইপযোগ্য কার্ড প্রদর্শনের জন্য দুর্দান্ত। আপনি যদি একটি ক্রিয়াকলাপ তৈরি করেন তবে আপনি CardScrollView উইজেট দিয়ে একই ধরণের প্রভাব তৈরি করতে পারেন।

  1. CardScrollView এ কার্ড সরবরাহ করতে একটি CardScrollAdapter প্রয়োগ করুন। আপনি নিজেই একটি স্ট্যান্ডার্ড ভিউ হায়ারার্কি তৈরি করতে পারেন বা CardBuilder ক্লাস ব্যবহার করতে পারেন।
  2. একটি CardScrollView তৈরি করুন যা কার্ডের সরবরাহকারী হিসাবে CardScrollAdapter ব্যবহার করে।
  3. আপনার কার্যকলাপের বিষয়বস্তু দৃশ্যটিকে CardScrollView হিসাবে সেট করুন বা একটি লেআউটে CardScrollView প্রদর্শন করুন৷

এখানে একটি সহজ বাস্তবায়ন যা তিনটি কার্ডের মাধ্যমে স্ক্রোল করে:

public class CardScrollActivity extends Activity {

    private List<CardBuilder> mCards;
    private CardScrollView mCardScrollView;
    private ExampleCardScrollAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        createCards();

        mCardScrollView = new CardScrollView(this);
        mAdapter = new ExampleCardScrollAdapter();
        mCardScrollView.setAdapter(mAdapter);
        mCardScrollView.activate();
        setContentView(mCardScrollView);
    }

    private void createCards() {
        mCards = new ArrayList<CardBuilder>();

        mCards.add(new CardBuilder(this, CardBuilder.Layout.TEXT)
                .setText("This card has a footer.")
                .setFootnote("I'm the footer!"));

        mCards.add(new CardBuilder(this, CardBuilder.Layout.CAPTION)
                .setText("This card has a puppy background image.")
                .setFootnote("How can you resist?")
                .addImage(R.drawable.puppy_bg));

        mCards.add(new CardBuilder(this, CardBuilder.Layout.COLUMNS)
                .setText("This card has a mosaic of puppies.")
                .setFootnote("Aren't they precious?")
                .addImage(R.drawable.puppy_small_1);
                .addImage(R.drawable.puppy_small_2);
                .addImage(R.drawable.puppy_small_3));
    }

    private class ExampleCardScrollAdapter extends CardScrollAdapter {

        @Override
        public int getPosition(Object item) {
            return mCards.indexOf(item);
        }

        @Override
        public int getCount() {
            return mCards.size();
        }

        @Override
        public Object getItem(int position) {
            return mCards.get(position);
        }

        @Override
        public int getViewTypeCount() {
            return CardBuilder.getViewTypeCount();
        }

        @Override
        public int getItemViewType(int position){
            return mCards.get(position).getItemViewType();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return mCards.get(position).getView(convertView, parent);
        }
    }
}

স্ক্রলিং কার্ডের সাথে ইন্টারঅ্যাক্ট করা

যেহেতু CardScrollView AdapterView প্রসারিত করে আপনি স্ট্যান্ডার্ড অ্যান্ড্রয়েড শ্রোতাদের বাস্তবায়ন করতে পারেন।

  1. আপনার CardScrollView এ উত্তরাধিকারসূত্রে প্রাপ্ত setOnItemClickListener() কল করুন।
  2. ট্যাপ ইভেন্টের জন্য একটি onItemClick() হ্যান্ডলার প্রয়োগ করুন।

এখানে পূর্ববর্তী উদাহরণের একটি এক্সটেনশন রয়েছে যা আপনি যখন একটি কার্ডে ট্যাপ করেন তখন একটি ট্যাপ শব্দ বাজায়:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        setupClickListener();
        setContentView(mCardScrollView);
    }

    private void setupClickListener() {
        mCardScrollView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
                am.playSoundEffect(Sounds.TAP);
            }
        });
    }

অ্যানিমেটিং স্ক্রলিং কার্ড

স্ক্রলিং কার্ডের জন্য তিনটি অ্যানিমেশন উপলব্ধ: নেভিগেশন, সন্নিবেশ এবং মুছে ফেলা।

  1. কার্ড সেটে একটি নির্দিষ্ট অবস্থানে একটি কার্ডে একটি সন্নিবেশ বা মুছে ফেলার ক্রিয়া প্রয়োগ করুন৷
  2. animate() কল করুন এবং CardScrollView.Animation enum থেকে একটি মান ব্যবহার করুন।
  3. একটি মসৃণ অ্যানিমেশন প্রদর্শন করার জন্য, notifyDataSetChanged() -এর যেকোনো রেফারেন্স মুছে ফেলুন। animate() পদ্ধতি আপনার ডেটা সেট ভিউ আপডেট করে।

    private class ExampleCardScrollAdapter extends CardScrollAdapter {
        ...
    
        // Inserts a card into the adapter, without notifying.
        public void insertCardWithoutNotification(int position, CardBuilder card) {
            mCards.add(position, card);
        }
    }
    
    private void insertNewCard(int position, CardBuilder card) {
        // Insert new card in the adapter, but don't call
        // notifyDataSetChanged() yet. Instead, request proper animation
        // to inserted card from card scroller, which will notify the
        // adapter at the right time during the animation.
        mAdapter.insertCardWithoutNotification(position, card);
        mCardScrollView.animate(position, CardScrollView.Animation.INSERTION);
    }
    

স্ক্রলিং কার্ডের জন্য কর্মক্ষমতা এবং বাস্তবায়ন টিপস

কার্ড স্ক্রলার তৈরি করার সময় নিম্নলিখিত নকশা এবং কর্মক্ষমতা প্রভাব মনে রাখবেন।

কার্ডের জীবনচক্র

কর্মক্ষমতা বাড়াতে, একটি CardScrollView শুধুমাত্র কার্ডের একটি উপসেট লোড করে যা একটি CardScrollAdapter প্রদান করে (সাধারণত, ব্যবহারকারীর কাছে দৃশ্যমান, এবং আরও কয়েকটি)। এই কারণে, একটি কার্ড এই চারটি সাধারণ অবস্থার যেকোনো একটিতে হতে পারে:

  • বিচ্ছিন্ন - বর্তমান সময়ে কার্ড স্ক্রোল ভিউতে এই কার্ডের প্রয়োজন নেই৷ কার্ডের onDetachedToWindow() পদ্ধতির মাধ্যমে আপনাকে অবহিত করা হবে যদি একটি কার্ড পূর্বে সংযুক্ত করা হয় এবং তারপর আলাদা করা হয়।
  • সংযুক্ত - কার্ড স্ক্রোল ভিউ অ্যাডাপ্টার থেকে getView() সহ কার্ডের জন্য অনুরোধ করে, কারণ কার্ডটি "সক্রিয়" হওয়ার কাছাকাছি। এটি ঘটলে আপনাকে কার্ডের onAttachedToWindow() পদ্ধতি দ্বারা অবহিত করা হবে৷
  • সক্রিয় - কার্ডটি ব্যবহারকারীর কাছে আংশিকভাবে দৃশ্যমান, কিন্তু কার্ড স্ক্রোল ভিউ ব্যবহারকারীর কাছে প্রদর্শনের জন্য কার্ডটিকে "নির্বাচিত" করেনি। এই ক্ষেত্রে 'isActivated()' পদ্ধতিটি true হয়।
  • নির্বাচিত - কার্ডটি ব্যবহারকারীর পুরো স্ক্রিনটি গ্রহণ করছে৷ getSelectedView() কল করা বর্তমানে নির্বাচিত কার্ড ফেরত দেয়। এই ক্ষেত্রে isSelected() পদ্ধতিটি সত্য দেখায়।

আপনি যদি আপনার কার্ডের ভিউ অ্যানিমেট করে থাকেন বা অন্যান্য ব্যয়বহুল ক্রিয়াকলাপগুলি করেন তবে সংস্থানগুলি সংরক্ষণ করতে onAttachedToWindow() এবং onDetachedToWindow() এ ক্রিয়াকলাপগুলি শুরু করুন এবং বন্ধ করুন৷

কার্ড রিসাইক্লিং

যখন একটি কার্ড সংযুক্ত হওয়া থেকে বিচ্ছিন্ন হয়ে যায়, তখন কার্ডের সাথে যুক্ত ভিউ অবজেক্টটি সংযুক্ত করা একটি কার্ড দ্বারা পুনর্ব্যবহৃত এবং ব্যবহার করা যেতে পারে। আপডেট তথ্যের সাথে রিসাইক্লিং ভিউ নতুন ভিউ তৈরি করার চেয়ে অনেক বেশি কার্যকর।

কার্ড রিসাইক্লিংয়ের সুবিধা নিতে, CardScrollAdapter ক্লাসের getItemViewType() , getViewTypeCount() , এবং getView() পদ্ধতিগুলি প্রয়োগ করুন৷ তারপরে আপনি আপনার CardScrollAdapter এ পুনর্ব্যবহার করার জন্য CardBuilder ক্লাসের কিছু সুবিধার পদ্ধতি ব্যবহার করেন, যেমন নিম্নলিখিত উদাহরণে:

private List<CardBuilder> mCards;
...
/**
 * Returns the number of view types for the CardBuilder class. The
 * CardBuilder class has a convenience method that returns this value for
 * you.
 */
@Override
public int getViewTypeCount() {
    return CardBuilder.getViewTypeCount();
}

/**
 * Returns the view type of this card, so the system can figure out
 * if it can be recycled. The CardBuilder.getItemViewType() method
 * returns it's own type.
 */
@Override
public int getItemViewType(int position){
    return mCards.get(position).getItemViewType();
}

/**
 * When requesting a card from the adapter, recycle the view if possible.
 * The CardBuilder.getView() method automatically recycles the convertView
 * it receives, if possible, or creates a new view if convertView is null or
 * of the wrong type.
 */
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    return  mCards.get(position).getView(convertView, parent);
}

স্থিতিশীল কার্ড আইডি বাস্তবায়ন করা

যখন একটি কার্ড নির্বাচন করা হয় এবং ব্যবহারকারীদের কাছে প্রদর্শিত হয়, তখন ব্যবহারকারীরা সেই মুহূর্তে যে কার্ডটি দেখেন সেটিকে প্রভাবিত করতে আপনি অন্তর্নিহিত অ্যাডাপ্টারের পরিবর্তনগুলি নাও চাইতে পারেন। উদাহরণস্বরূপ, যদি একজন ব্যবহারকারী একটি নির্বাচিত কার্ড দেখছেন, এবং সেই কার্ডের বাম দিকে একটি কার্ড সরানো হয়, ব্যবহারকারী যে কার্ডটি দেখছেন তা সম্ভবত বাম দিকে স্থানান্তরিত হতে পারে, কারণ পরিবর্তন ঘটলে CardScrollAdapter অন্তর্নিহিত ডেটা সেটে আইডি পুনরায় বরাদ্দ করে। , ডিফল্টরূপে।

যদি যৌক্তিকভাবে আপনার কার্ডগুলিকে অনন্য আইডি বরাদ্দ করাটা বোধগম্য হয়, তাহলে আপনি উপরে উল্লিখিত সমস্যা রোধ করতে অন্তর্নিহিত ডেটা সেটে একটি সামঞ্জস্যপূর্ণ আইডি বজায় রাখতে পারেন। এটি করার জন্য, hasStableIds() ওভাররাইড করুন এবং true রিটার্ন করুন। এটি সিস্টেমে সুনির্দিষ্ট করে যে CardScrollAdapter ডেটা সেটের পরিবর্তন জুড়ে স্থিতিশীল আইডি বজায় রাখে। এছাড়াও, আপনার অ্যাডাপ্টারের কার্ডগুলির জন্য উপযুক্ত অনন্য আইডি ফেরত দিতে getItemId() প্রয়োগ করুন৷ ডিফল্ট বাস্তবায়ন অ্যাডাপ্টারে কার্ডের অবস্থানের সূচী প্রদান করে, যা সহজাতভাবে অস্থির।

খালি কার্ডস্ক্রোল অ্যাডাপ্টার

যখন আপনার অ্যাডাপ্টারের জন্য একটি খালি ডেটা সেট থাকে, তখন ডিফল্ট ভিউটি একটি কালো স্ক্রিন দেখানো হয়। আপনি যদি এই ক্ষেত্রে একটি ভিন্ন দৃশ্য দেখাতে চান, setEmptyView() ব্যবহার করবেন না। পরিবর্তে, আপনার CardScrollAdapter এ একটি একক কার্ড তৈরি করুন।

অনুভূমিক টাগিং প্রতিক্রিয়া

গ্লাসে অনেক অন্তর্নির্মিত নিমজ্জনগুলি "টাগিং" প্রতিক্রিয়া প্রদান করে যখন পিছনের দিকে এবং সামনের দিকে সোয়াইপ করার সময় কোনও ক্রিয়া সম্পাদন করে না। উদাহরণস্বরূপ, একটি ফটো তোলার পরে সোয়াইপ করার সময় আপনি এই প্রতিক্রিয়াটি দেখতে পারেন৷

যদি আপনার নিমজ্জন অ্যাপ্লিকেশন-নির্দিষ্ট ফাংশন সঞ্চালনের জন্য অনুভূমিক সোয়াইপ অঙ্গভঙ্গি ব্যবহার না করে, তাহলে একটি কার্ড ধারণ করে এমন একটি CardScrollView এর ভিতরে আপনার লেআউটটি মোড়ানোর মাধ্যমে এই টাগিং প্রভাব প্রদান করুন৷

  1. আপনার প্রকল্পে নিম্নলিখিত সহায়ক শ্রেণী অনুলিপি করুন:

    public class TuggableView extends CardScrollView {
    
        private final View mContentView;
    
        /**
         * Initializes a TuggableView that uses the specified layout
         * resource for its user interface.
         */
        public TuggableView(Context context, int layoutResId) {
            this(context, LayoutInflater.from(context)
                    .inflate(layoutResId, null));
        }
    
        /**
         * Initializes a TuggableView that uses the specified view
         * for its user interface.
         */
        public TuggableView(Context context, View view) {
            super(context);
    
            mContentView = view;
            setAdapter(new SingleCardAdapter());
            activate();
        }
    
        /**
         * Overridden to return false so that all motion events still
         * bubble up to the activity's onGenericMotionEvent() method after
         * they are handled by the card scroller. This allows the activity
         * to handle TAP gestures using a GestureDetector instead of the
         * card scroller's OnItemClickedListener.
         */
        @Override
        protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
            super.dispatchGenericFocusedEvent(event);
            return false;
        }
    
        /** Holds the single "card" inside the card scroll view. */
        private class SingleCardAdapter extends CardScrollAdapter {
    
            @Override
            public int getPosition(Object item) {
                return 0;
            }
    
            @Override
            public int getCount() {
                return 1;
            }
    
            @Override
            public Object getItem(int position) {
                return mContentView;
            }
    
            @Override
            public View getView(int position, View recycleView,
                    ViewGroup parent) {
                return mContentView;
            }
        }
    }
    
  2. আপনার লেআউট ধারণকারী CardScrollView প্রদর্শন করতে আপনার কার্যকলাপে onCreate পদ্ধতি পরিবর্তন করুন।

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        // was: setContentView(R.layout.main_activity);
        setContentView(new TuggableView(this, R.layout.main_activity));
    }