#notifydatasetchanged
Explore tagged Tumblr posts
harmonyos-next · 3 months ago
Text
HarmonyOS NEXT Practical: Waterfall Flow and LazyForeach
Goal: Implement waterfall flow images and text, and load waterfall flow sub items through lazy loading.
Implementation idea:
Create a Card model
Create WaterFlowDataSource data source
Customize WaterFlowVNet Component Custom Components
Implement WaterFlow and LazyForEach loops on the page
WaterFlow The waterfall container is composed of cells separated by rows and columns. Through the container's own arrangement rules, different sized items are arranged tightly from top to bottom, like a waterfall. Only supports FlowItem sub components and supports rendering control types (if/else, ForEach, LazyForEach, and Repeat).
Actual combat: WaterFlowDataSource [code] // An object that implements the iPadOS Source interface for loading data into waterfall components export class WaterFlowDataSource implements IDataSource { private dataArray: Card[] = []; private listeners: DataChangeListener[] = [];
constructor() { this.dataArray.push({ image: $r('app.media.img_1'), imageWidth: 162, imageHeight: 130, text: 'Ice cream is made with carrageenan …', buttonLabel: 'View article' }); this.dataArray.push({ image: $r('app.media.img_2'), imageWidth: '100%', imageHeight: 117, text: 'Is makeup one of your daily esse …', buttonLabel: 'View article' }); this.dataArray.push({ image: $r('app.media.img_3'), imageWidth: '100%', imageHeight: 117, text: 'Coffee is more than just a drink: It’s …', buttonLabel: 'View article' }); this.dataArray.push({ image: $r('app.media.img_4'), imageWidth: 162, imageHeight: 130, text: 'Fashion is a popular style, especially in …', buttonLabel: 'View article' }); this.dataArray.push({ image: $r('app.media.img_5'), imageWidth: '100%', imageHeight: 206, text: 'Argon is a great free UI packag …', buttonLabel: 'View article' }); }
// 获取索引对应的数据 public getData(index: number): Card { return this.dataArray[index]; }
// 通知控制器数据重新加载 notifyDataReload(): void { this.listeners.forEach(listener => { listener.onDataReloaded(); }) }
// 通知控制器数据增加 notifyDataAdd(index: number): void { this.listeners.forEach(listener => { listener.onDataAdd(index); }) }
// 通知控制器数据变化 notifyDataChange(index: number): void { this.listeners.forEach(listener => { listener.onDataChange(index); }) }
// 通知控制器数据删除 notifyDataDelete(index: number): void { this.listeners.forEach(listener => { listener.onDataDelete(index); }) }
// 通知控制器数据位置变化 notifyDataMove(from: number, to: number): void { this.listeners.forEach(listener => { listener.onDataMove(from, to); }) }
//通知控制器数据批量修改 notifyDatasetChange(operations: DataOperation[]): void { this.listeners.forEach(listener => { listener.onDatasetChange(operations); }) }
// 获取数据总数 public totalCount(): number { return this.dataArray.length; }
// 注册改变数据的控制器 registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0) { this.listeners.push(listener); } }
// 注销改变数据的控制器 unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos >= 0) { this.listeners.splice(pos, 1); } }
// 增加数据 public add1stItem(card: Card): void { this.dataArray.splice(0, 0, card); this.notifyDataAdd(0); }
// 在数据尾部增加一个元素 public addLastItem(card: Card): void { this.dataArray.splice(this.dataArray.length, 0, card); this.notifyDataAdd(this.dataArray.length - 1); }
public addDemoDataAtLast(): void { this.dataArray.push({ image: $r('app.media.img_1'), imageWidth: 162, imageHeight: 130, text: 'Ice cream is made with carrageenan …', buttonLabel: 'View article' }); this.dataArray.push({ image: $r('app.media.img_2'), imageWidth: '100%', imageHeight: 117, text: 'Is makeup one of your daily esse …', buttonLabel: 'View article' }); this.dataArray.push({ image: $r('app.media.img_3'), imageWidth: '100%', imageHeight: 117, text: 'Coffee is more than just a drink: It’s …', buttonLabel: 'View article' }); this.dataArray.push({ image: $r('app.media.img_4'), imageWidth: 162, imageHeight: 130, text: 'Fashion is a popular style, especially in …', buttonLabel: 'View article' }); this.dataArray.push({ image: $r('app.media.img_5'), imageWidth: '100%', imageHeight: 206, text: 'Argon is a great free UI packag …', buttonLabel: 'View article' }); }
// 在指定索引位置增加一个元素 public addItem(index: number, card: Card): void { this.dataArray.splice(index, 0, card); this.notifyDataAdd(index); }
// 删除第一个元素 public delete1stItem(): void { this.dataArray.splice(0, 1); this.notifyDataDelete(0); }
// 删除第二个元素 public delete2ndItem(): void { this.dataArray.splice(1, 1); this.notifyDataDelete(1); }
// 删除最后一个元素 public deleteLastItem(): void { this.dataArray.splice(-1, 1); this.notifyDataDelete(this.dataArray.length); }
// 在指定索引位置删除一个元素 public deleteItem(index: number): void { this.dataArray.splice(index, 1); this.notifyDataDelete(index); }
// 重新加载数据 public reload(): void { this.dataArray.splice(1, 1); this.dataArray.splice(3, 2); this.notifyDataReload(); } }
export interface Card { image: Resource //图片 imageWidth: Length //图片宽度 imageHeight: Length //图片高度 text: string //文字 buttonLabel: string //按钮文字 } [/code] WaterFlowItemComponent [code] import { Card } from "./WaterFlowDataSource";
// @Reusable @Component export struct WaterFlowItemComponent { @Prop item: Card
// 从复用缓存中加入到组件树之前调用,可在此处更新组件的状态变量以展示正确的内容 aboutToReuse(params: Record) { this.item = params.item; console.info('Reuse item:' + JSON.stringify(this.item)); }
aboutToAppear() { console.info('new item:' + JSON.stringify(this.item)); }
build() { if (this.item.imageWidth == '100%') { Column() { Image(this.item.image) .width(this.item.imageWidth) .height(this.item.imageHeight) Column() { Text(this.item.text) .fontWeight(400) .fontColor('#32325D') .fontSize(14) .lineHeight(18) Text(this.item.buttonLabel) .fontWeight(700) .fontColor('#5E72E4') .fontSize(12) .lineHeight(17) } .width('100%') .padding(12) .layoutWeight(1) .alignItems(HorizontalAlign.Start) .justifyContent(FlexAlign.SpaceBetween) } .width('100%') .height('100%') .alignItems(HorizontalAlign.Start) } else { Row() { Image(this.item.image) .width(this.item.imageWidth) .height(this.item.imageHeight) Column() { Text(this.item.text) .fontWeight(400) .fontColor('#32325D') .fontSize(14) .lineHeight(18) Text(this.item.buttonLabel) .fontWeight(700) .fontColor('#5E72E4') .fontSize(12) .lineHeight(17) } .height('100%') .layoutWeight(1) .alignItems(HorizontalAlign.Start) .padding(12) .justifyContent(FlexAlign.SpaceBetween) } .width('100%') .height('100%') }
} } [/code] WaterFlowDemoPage [code] import { Card, WaterFlowDataSource } from './WaterFlowDataSource'; import { WaterFlowItemComponent } from './WaterFlowItemComponent';
@Entry @Component export struct WaterFlowDemoPage { minSize: number = 80; maxSize: number = 180; fontSize: number = 24; scroller: Scroller = new Scroller(); dataSource: WaterFlowDataSource = new WaterFlowDataSource(); dataCount: number = this.dataSource.totalCount(); private itemHeightArray: number[] = []; @State sections: WaterFlowSections = new WaterFlowSections(); sectionMargin: Margin = { top: 10, left: 20, bottom: 10, right: 20 };
// 设置FlowItem的高度数组 setItemSizeArray() { this.itemHeightArray.push(130); this.itemHeightArray.push(212); this.itemHeightArray.push(212); this.itemHeightArray.push(130); this.itemHeightArray.push(268); }
aboutToAppear() { this.setItemSizeArray(); this.addSectionOptions(true); for (let index = 0; index < 10; index++) { this.dataSource.addDemoDataAtLast(); this.setItemSizeArray(); this.addSectionOptions(); } }
addSectionOptions(isFirstAdd: boolean = false) { this.sections.push({ itemsCount: 1, crossCount: 1, margin: isFirstAdd ? { top: 20, left: 20, bottom: 10, right: 20 } : this.sectionMargin, onGetItemMainSizeByIndex: (index: number) => { return 130; } }) this.sections.push({ itemsCount: 2, crossCount: 2, rowsGap: '20vp', margin: this.sectionMargin, onGetItemMainSizeByIndex: (index: number) => { return 212; } }) this.sections.push({ itemsCount: 1, crossCount: 1, margin: this.sectionMargin, onGetItemMainSizeByIndex: (index: number) => { return 130; } }) this.sections.push({ itemsCount: 1, crossCount: 1, rowsGap: '20vp', columnsGap: '20vp', margin: this.sectionMargin, onGetItemMainSizeByIndex: (index: number) => { return 268; } }) }
build() { Column({ space: 2 }) { WaterFlow({ scroller: this.scroller, sections: this.sections }) { LazyForEach(this.dataSource, (item: Card, index: number) => { FlowItem() { WaterFlowItemComponent({ item: item }) } .width('100%') .backgroundColor(Color.White) .borderRadius(6) .clip(true) }, (item: Card, index: number) => index.toString()) } // .columnsTemplate('1fr 1fr') // 瀑布流使用sections参数时该属性无效 .columnsGap(14) .rowsGap(20) .backgroundColor('#F8F9FE') .width('100%') .height('100%') .layoutWeight(1) } } } [/code]
0 notes
thelord89slot · 1 year ago
Text
ปีที่ทีมเชลซีชนะในการแข่งขัน Piala FA ในอังกฤษครั้งล่าสุดคือปีใด?
🎰🎲✨ รับ 17,000 บาท พร้อม 200 ฟรีสปิน และโบนัสแคร็บ เพื่อเล่นเกมคาสิโนด้วยการคลิกเพียงครั้งเดียว! ✨🎲🎰
ปีที่ทีมเชลซีชนะในการแข่งขัน Piala FA ในอังกฤษครั้งล่าสุดคือปีใด?
ในปีที่ทีมเชลซีชนะ ฟุตบอลเป็นกีฬาที่มีความนิยมอย่างแพร่หลายทั่วโลก การชนะในการแข่งขันใด ๆ เป็นเหตุการณ์ที่เป็นที่ชื่นชมอย่างมาก เชลซีเป็นทีมฟุตบอลที่มีประวัติศาสตร์ยาวนานและมีผลงานที่น่าทึ่งมากมาย
ในปีที่ทีมเชลซีชนะอาจมีหลายสถานการณ์ที่ทำให้ทีมได้รับชัยชนะ เช่นการเปิดบอลในวินาทีสุดท้ายของเกม การทำประตูสุดท้ายที่ทำให้คะแนนเกมเทา การป้องกันอย่างแข้งแรลง เป็นเพียงตัวอย่างอีกข้อที่ทำให้เชลซีเป็นทีมชั้นนำ
การชนะของทีมเชลซีอาจมีผลกระทบที่หลากหลายในชุมชนฟุตบอลทั้งโลก ส่งผลให้ผู้ชมรู้สึกยินดี มีผลกระทบต่อโอกาสในการจัดเกม และสร้างแรงบันดาลใจให้กับนักกีฬาอย่างมาก
การชนะของทีมเชลซีในปีนั้นอาจเป็นเหตุผลสำคัญที่ทำให้แฟนบอลภายในประเทศและต่างประเทศต้องเอำชีวิตในทุกองศา เชลซีเป็นทีมที่มีแฟนคลับจำนวนมาก ที่อยู่บนเส้นฟันชั่นของอารยธรรมโดยทั่วไป
ในสรุป ปีที่ทีมเชลซีชนะมีความสำคัญอย่างมากทั้งอาทิตย์นี้และอนาคต การชนะในการแข่งขันเป็นเหตุการณ์ที่ทำให้ทุกคนรู้สึกภูมิใจและกระต่ายยากใจในทีมที่ตนเองรัก ไม่ว่าเป็นผู้ชมที่มาร่วมสนุก หรือผู้เกี่ยวข้องในวงการฟุตบอล ผู้คนทุกคนจะมีความสุขและได้รับประโยชน์จากความสำเร็จนี้
ข่าวการกีฬา: 2. Piala FA ในอังกฤษ
ในโลกของกีฬาฟุตบอลในอังกฤษ การเอาชนะในการแข่งขัน Piala FA เป็นเป้าหมายที่ทุกทีมมุ่งเน้นอย่างมาก เนื่องจากเป็นแข่ง���ละประลองที่มีประวัติยาวนาน ที่เริ่มแข่งมาตั้งแต่ปี 1871 โดยแข่งกันทั้งทีมของลีกอาชีวะและทีมจากลีกนอก เป็นที่รู้จักด้วยความเข้มข้นและอารมณ์กันแบบเริ่ดรัน
การแข่งขันในทุกเทม ไม่ว่าจะเป็นที่สูงสุดในลีก หรือทีมจากลีกน้อย การชนะ Piala FA ถือเป็นเกียรติยศที่สำคัญ และยิ่งเพิ่มความสำคัญในทีมที่ไม่ได้ผลิตแชมป์ในรอบเวลาอันยาวนาน การเอาชนะใน Piala FA ทำให้ทีมสามารถได้รับเข้าร่วมแข่งขันในลีกยูโรป้า ทำให้ชดเชยสำหรับผลงานที่ไม่ได็หรับในลีก
ในปัจจุบัน ทีมที่ทำได้เด่นในการแข่งขัน Piala FA คือ ทีมอาร์เซนอล, เชลซี และแมนเชสเตอร์ ยูไนเต็ด ที่ได้เข้าสู่รอบชิงชนะเลิศอย่างสามารถาน เมื่อปีที่แล้ว เชลซีได้เอาชนะมาเลิง ในรอบชิงชนะเลิศแข่งขัน Piala FA ก่อนที่เฮิร์ทส์หน้าจะเป็นสรปอีกมากในสานงจะนี้.
ในสร้างนี้จะเปเอบ เพื่สาใหรัวการา ไว้ใบบาแข่งขัน฽ย็นถัรทังลงเอาวสตาี่นแุนลาเปบทอาสารส่ารแรงกีลบ่นดนางบดโารเอาวงนสหโกตคนใบิด้รารว่ารยืใควนใงสลจ แสลุันทีงวาคสูคืเงาแทดด เฟรรนิญละบ้นจเส เวํ้คฏทด.
ขณะที่การแข่งขันอาจทำให้ความแข็งขันกับผู้อื่น เพิ่มความสามารถในการทำงานร่วม และส่งผลให้กลุ่มเชื่อมั่นกับความสำเร็จของระดับรายบุคคล อีกทั้งก็ช่วยส่งเสริมพัฒนาการและการเรียนรู้ หลายๆ วิทยากรให้ความสำคัญกับการแข่งขันในชีวิตประจำวัน เนื่องจากมีหลากหลายผลกระทบที่เกิดขึ้นจากการแข่งขัน ไม่ว่าจะเป็นการเสริมสร้างสมรรถนะ สร้างกล้าหาญ และการกระตุ้นความคิดสร้างสรรค์
การแข่งขันยังช่วยสร้างตำแหน่งการงาน ลดความเบื่อหน่าย และสร้างข้อแสดงความรู้สึกสว่างโลก ประชาสัมพันธ์ทางภาคเขตได้มอบกวาดูขดเจ่าก๊นับ, โดยนักสมาชิกอาจสร้างสรรค์งานใหม่ ตื่นตัวที่ผ่านเข้าได้เลียยกบริบู่หลายๆ อย่าง เช่นโดยการฉาบพยายามในโลกที่ใกล้มีความแรงกระฉั่นแท้เน, แท้=test และปลอดคลำคลี่
การแข่งขันยังสร้างเรื่องขึ้นการเรียนำเรียงข้อมูล, พยางานใ.notifyDataSetChangedการข้อมูลที่ต้องการ, การทำผลสืบรวบรวม, และก็การมือปืม็ตมือ การแข่งขันยังดูเหมือนด้วยการJumbleยึดข้อเกณฑ์ใNew เมื่อคุณตาส-removeเน็ดและเรียกนั้กกร้อยบทร้้าันบารับว่าเหยำส็รงค่าผวาเพ��มินำการด่วยตำด้เสหยิถสรงบรำหาแรยี่สึก ถับ่าหลายทู่ชงทู่โบร้โล่เทียาบสเ็มี็ต็ุำสำำส่้าบบยำ บำยีสะำบคุ่เส้อราบำใ็สแ็บำบำ บ็ารสำ้บ- บบยป้ำ ้อมำบำย บ็ารสำ้บกำยยย้ำ201-202ำบำ่ำบยำ บ็ารสำ้บยะโดูำเ่ณ่ำำบำยยำอ- ใบย็่ำบับ่ำี่บ่ไส่บีย้ายำาำ้อคำยำ ี้ ่ำำยื่
ในโลกปัจจุบันที่เต็มไปด้วยความร้อนและความขมขื่นของชีวิตประจำวัน มาถึง ครั้งล่าสุด เป็นช่วงเวลาที่เรามักจะกังวลเกี่ยวกับผลลัพธ์ของความพยายามของเรา แต่ในความสุขเพราะ ครั้งล่าสุด ไม่ใช่เพียงแค่เวลาที่คุณทำได้ดี แต่เป็นเวลาที่คุณเริ่มสัมผัสถึงความพอใจที่มาพร้อมกับความสำเร็จของคุณด้วย
การมองไปที่ครั้งล่าสุดให้เรารำนาจเราอย่างชัดเจนว่าเรามีความเห็นที่ดีกับตัวเราเอง และอีกอย่างที่สำคัญคือเรามีความเข้าใจกับว่าความพยายามของเรามีค่าอย่างไรต่อชีวิตและอนาคตของเรา
ไม่ว่ามันจะเป็นการสำเร็จในการงาน, การเรียน, หรือในความสัมพันธ์ ครั้งล่าสุดคือการที่เราเริ่มเห็นว่าการพยายามของเรามีค่ามากขึ้น และเราควรเป็นภาคผ่อนคลาย และภาคพิมพ์สุขในตัวเราเอง
การเปลี่ยนแปลงที่เกิดขึ้นในชีวิตในช่วงเวลานี้อาจเป็นขั้นแรกสู่ภาพลักษณ์ใหม่ของคุณ ครั้งล่าสุดไม่เพียงแค่เป็นจุดเริ่มต้น แต่ยังเป็นการพิสูจน์ภาพลักษณ์ของคุณว่าคุณสมบูรณ์แล้วและมีคุณค่า
จงกระตือรือร้นในความสำเร็จของคุณใน ครั้งล่าสุด และเชื่อว่ามันเป็นเพียงเริ่มต้นของความสุขและความเจริญรุ่งเรืองของคุณในอนาคตที่กำลังมา.
"5. ปีที่ทีมชนะ" เป็นเวลาที่ความพยายามและการทำงานทีมเป็นผลต่อการชนะในการแข่งขัน การทีมชนะไม่เป็นเรื่องง่ายเพียงแค่เล่นดีในหนึ่งเกมเท่านั้น มันเกิดจากการฝึกระบบการทำงานร่วมกันอย่างต่อเนื่อง บนสนามแข่งขันทีมแต่ละทีมต้องมีความร่วมมือและความตั้งใจที่แท้จริง ทีมที่มีความเข้มแข็งและตั้งใจที่จะชนะจะมีโอกาสที่ดีที่จะเอาชนะมาได้อย่างสม่ำเสมอ
การทีมชนะเป็นผลลัพธ์ของการฝึกฝนอย่างสม่ำเสมอและการเตรียมความพร้อมอย่างดีก่อนการแข่งขัน มันไม่เพียงแค่เรื่องของความสามารถในฝีมือเท่านั้น แต่ยังความก้าวหน้าและการวางแผนที่ดี เพื่อให้ทีมเกิดผลลัพธ์ที่ต้องการได้ อีกทั้งยังต้องมีความเอื้อให้จากผู้จัดการทีมที่สามารถชั้นนำและกำหนดทิศทางให้ทีมไปให้ถูกทิศ
ในที่สุด 5. ปีที่ทีมชนะ ไม่ได้แสดงถึงตอนท้ายของความพยายาม แต่เป็นจุดเริ่มต้นของความสำเร็จที่ยาวนาน การเรียนรู้จากความผิดพลาดและพัฒนาต่อ���อดจากประสบการณ์ความชนะเป็นสิ่งสำคัญที่สุดที่ทำให้ทีมสามารถทำให้เหนับซนกว่าเดิมและสร้างชื่อเสียงให้กับตนเองในวงการ"
0 notes
fooooooooooooooooool · 3 years ago
Text
【Android】RecyclerView数据刷新
[太长不看] 使用notifyItemRangeChanged()方法刷新数据,保持焦点 [问题现象] RecyclerView刷新数据后焦点乱跳 [问题分析] 找到刷新数据位置,查到刷新时使用notifyDataSetChanged()方法刷新View,导致页面焦点重置,出现焦点乱跳 [源码资料] 方法1: notifyItemRangeChanged() public final void notifyItemRangeChanged(int positionStart, int itemCount)  /** Notify any registered observers that the itemCount items starting at position positionStart have changed. Equivalent to calling…
View On WordPress
0 notes
jacob-cs · 5 years ago
Text
kotlin backing fields
original source : https://kotlinlang.org/docs/reference/properties.html#backing-fields
https://codelabs.developers.google.com/codelabs/kotlin-android-training-recyclerview-fundamentals/index.html?index=..%2F..android-kotlin-fundamentals#3
var data =  listOf<SleepNight>()   set(value) {       field = value       notifyDataSetChanged()   }
이를 보다가 찾아 보게된 자료이다.
.
.
Backing Fields
Fields cannot be declared directly in Kotlin classes. However, when a property needs a backing field, Kotlin provides it automatically. This backing field can be referenced in the accessors using the   field   identifier:
var counter = 0 // Note: the initializer assigns the backing field directly    set(value) {        if (value >= 0) field = value    }
The field identifier can only be used in the accessors of the property.
A backing field will be generated for a property if it uses the default implementation of at least one of the accessors, or if a custom accessor references it through the   field   identifier.
For example, in the following case there will be no backing field:
val isEmpty: Boolean    get() = this.size == 0
kotlin android codelab 강좌에서 본적이 있음.
LiveData를 사용하기 위해서 MutableLiveData를 사용했음. 그와 비슷한 원리이다.
Backing Properties
If you want to do something that does not fit into this "implicit backing field" scheme, you can always fall back to having a backing property:
private var _table: Map<String, Int>? = null public val table: Map<String, Int>    get() {        if (_table == null) {            _table = HashMap() // Type parameters are inferred        }        return _table ?: throw AssertionError("Set to null by another thread")    }
On the JVM: The access to private properties with default getters and setters is optimized so no function call overhead is introduced in this case.
java의 field와 kotlin에서의 property의 개념 차이
https://blog.kotlin-academy.com/kotlin-programmer-dictionary-field-vs-property-30ab7ef70531
This is an example of a Java field:
public String name = "Marcin";
Here is an example of a Kotlin property:
var name: String = "Marcin"
They both look very similar, but these are two different concepts. Direct Java equivalent of above Kotlin property is following:
private String name = "Marcin";
public String getName() {    return name; }public void setName(String name) {    this.name = name; }
The default implementation of Kotlin property includes field and accessors (getter for val, and getter and setter for var). Thanks to that, we can always replace accessors default implementation with a custom one. For instance, if we want to accept only non-blank values, then we can define the following setter:
var name: String = "Marcin"    set(value) {        if (value.isNotBlank())            field = value    }name = "Marcin" name = "" print(name) // Prints: Marcin
If we want to be sure that the returned property value is capitalized, we can define a custom getter which capitalizes it:
var name: String = "Marcin"    get() = field.capitalize()name = "marcin" print(name) // Prints: Marcin
The key fact regarding properties is that they actually are defined by their accessors. A property does not need to include any field at all. When we define custom accessors that are not using any field, then the field is not generated:
var name: String    get() = "Marcin"
This is why we can use property delegation. See example of property delegate below:
var name: String by NameDelegate()
Above code is compiled to the following implementation:
val name$delegate = NameDelegate() var name: String    get() = name$delegate.getValue(this, this::name)    set(value) { name$delegate.setValue(this, this::name, value) }
Moreover, while a property is defined by its accessors, we can specify it in the interface:
interface Person {    val name: String }
Such declaration means that there must be a getter defined in classes that implement interface Person.
As you can clearly see, Kotlin properties give developers much bigger possibilities than Java fields. Yet, they look nearly the same and Kotlin properties can be used exactly the same as Java fields. This is a great example, how Kotlin hides complexity under the carpet and gives us possibilities even if some developers remain unaware of them.
This post is the fourth part of the Kotlin programmer dictionary. To stay up-to-date with new parts, just follow this medium or observe me on Twitter.
If you need some help then remember that I am open for consultations.
If you like it, remember to clap. Note that if you hold the clap button, you can leave more claps.
0 notes
holytheoristtastemaker · 5 years ago
Link
Let's say a user of your site wants to edit a list item without opening the item and looking for editing options. If you can enable this functionality, it gives that user a good User Experience. Pocket, a bookmarking app owned by Mozilla, does something similar. You can share/archive/delete your saved articles directly from the list without opening the article. Then you can click the menu button in the top-right corner and select your edit option. So in this tutorial we'll try to code this one out. Here's what we want to achieve:
First let’s create a normal RecyclerView list
RecyclerView is an advanced and flexible version of ListView and GridView. It's capable of holding large amounts of list data and has better performance than its predecessors. As the name suggests, RecyclerView 'recycles' the items of our list once it's out of view on scrolling and re-populates them when they come back to view. So the list container has to maintain only a limited number of views and not the entire list. It's so flexible that the new ViewPager2 class, used to create swipe-able tabs, is written over RecyclerView.
Create a POJO (Plain Old Java Object) to hold the list data
public class RecyclerEntity { private String title; private boolean showMenu = false; private int image; public RecyclerEntity() { } public RecyclerEntity(String title, int image, boolean showMenu) { this.title = title; this.showMenu = showMenu; this.image = image; } public int getImage() { return image; } public void setImage(int image) { this.image = image; } //... all the getters and setters }
Notice we have a showMenu member here which will handle the visibility of the menu for that list item in our RecyclerView.
Create a RecyclerView Adapter
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { List<RecyclerEntity> list; Context context; public RecyclerAdapter(Context context, List<RecyclerEntity> articlesList) { this.list = articlesList; this.context = context; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v; v= LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_list, parent, false); return new MyViewHolder(v); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { RecyclerEntity entity = list.get(position); if(holder instanceof MyViewHolder){ ((MyViewHolder)holder).title.setText(entity.getTitle()); ((MyViewHolder)holder).imageView.setImageDrawable(context.getResources().getDrawable(entity.getImage())); } } @Override public int getItemCount() { return list.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { TextView title; ImageView imageView; ConstraintLayout container; public MyViewHolder(View itemView) { super(itemView); title = itemView.findViewById(R.id.title); imageView = itemView.findViewById(R.id.imageView); container = itemView.findViewById(R.id.container); } } }
Usually we put our ViewHolder sub class (MyViewHolder) in the super class template. This lets us directly return our defined ViewHolder subclass object from the onCreateViewHolder() method. Then we don't have to cast it again and again in onBindViewHolder() method. But here we can't do that, and we'll learn why in a minute.
Initialise the RecyclerView in the Activity
public class MainActivity extends AppCompatActivity { RecyclerView recyclerView; List<RecyclerEntity> list; RecyclerAdapter adapter; @RequiresApi(api = Build.VERSION_CODES.M) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.recyclerview); list = new ArrayList<>(); list.add(new RecyclerEntity("This is the best title", R.drawable.one, false)); list.add(new RecyclerEntity("This is the second-best title", R.drawable.two, false)); //... rest of the list items adapter = new RecyclerAdapter(this, list); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); } }
Now let's start making things a little more interesting.
Create a layout resource for the menu
And initialise it in Recycler Adapter:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { List<RecyclerEntity> list; Context context; private final int SHOW_MENU = 1; private final int HIDE_MENU = 2; public RecyclerAdapter(Context context, List<RecyclerEntity> articlesList) { this.list = articlesList; this.context = context; } @Override public int getItemViewType(int position) { if(list.get(position).isShowMenu()){ return SHOW_MENU; }else{ return HIDE_MENU; } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v; if(viewType==SHOW_MENU){ v= LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_menu, parent, false); return new MenuViewHolder(v); }else{ v= LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_list, parent, false); return new MyViewHolder(v); } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { RecyclerEntity entity = list.get(position); if(holder instanceof MyViewHolder){ //... same as above } if(holder instanceof MenuViewHolder){ //Menu Actions } } @Override public int getItemCount() { return list.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { //... same as above } //Our menu view public class MenuViewHolder extends RecyclerView.ViewHolder{ public MenuViewHolder(View view){ super(view); } } }
Now we have two ViewHolder sub-classes in our adapter, MyViewHolder (the actual list item) and MenuViewHolder. Both inherit the same class so we return the parent class RecyclerView.ViewHolder from onCreateViewHolder(). Our getItemViewType() method returns the int variable (viewType) which tells the kind of view we want to show in our RecyclerView for a particular position: that is, either MyViewHolder or MenuViewHolder. This viewType variable is then used by onCreateViewHolder() which actually returns the respective ViewHolder object.
Add the functions to show/hide menu in RecyclerAdapter
public void showMenu(int position) { for(int i=0; i<list.size(); i++){ list.get(i).setShowMenu(false); } list.get(position).setShowMenu(true); notifyDataSetChanged(); } public boolean isMenuShown() { for(int i=0; i<list.size(); i++){ if(list.get(i).isShowMenu()){ return true; } } return false; } public void closeMenu() { for(int i=0; i<list.size(); i++){ list.get(i).setShowMenu(false); } notifyDataSetChanged(); }
Note that there are many ways to handle this. But for simplicity's sake we're keeping a boolean value in our POJO to maintain the menu's visibility. After changing our data list, we call the notifyDataSetChanged() method to redraw the list.
Show the menu on long press of our list item in RecyclerAdapter
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { RecyclerEntity entity = list.get(position); if(holder instanceof MyViewHolder){ ((MyViewHolder)holder).title.setText(entity.getTitle()); ((MyViewHolder)holder).imageView.setImageDrawable(context.getResources().getDrawable(entity.getImage())); ((MyViewHolder)holder).container.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { showMenu(position); return true; } }); } if(holder instanceof MenuViewHolder){ //Set Menu Actions like: //((MenuViewHolder)holder).edit.setOnClickListener(null); } }
Again, setting events on our views can also be done in various ways. In our example, we have three actions in our menu. You can write your logic to handle those actions in the second if statement like shown in the comments.
Show the menu on swipe
To do this, we add a touch helper in our MainActivity.java:
public class MainActivity extends AppCompatActivity { RecyclerView recyclerView; List<RecyclerEntity> list; RecyclerAdapter adapter; @RequiresApi(api = Build.VERSION_CODES.M) @Override protected void onCreate(Bundle savedInstanceState) { //... same as above adapter = new RecyclerAdapter(this, list); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(adapter); ItemTouchHelper.SimpleCallback touchHelperCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) { private final ColorDrawable background = new ColorDrawable(getResources().getColor(R.color.background)); @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { adapter.showMenu(viewHolder.getAdapterPosition()); } @Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); View itemView = viewHolder.itemView; if (dX > 0) { background.setBounds(itemView.getLeft(), itemView.getTop(), itemView.getLeft() + ((int) dX), itemView.getBottom()); } else if (dX < 0) { background.setBounds(itemView.getRight() + ((int) dX), itemView.getTop(), itemView.getRight(), itemView.getBottom()); } else { background.setBounds(0, 0, 0, 0); } background.draw(c); } }; ItemTouchHelper itemTouchHelper = new ItemTouchHelper(touchHelperCallback); itemTouchHelper.attachToRecyclerView(recyclerView); }
We call the showMenu() function inside our adapter when a list item is swiped. The onChildDraw() function draws the background while we swipe. Otherwise there'll be a white background while swiping and our menu layout will show up with a pop.
Hiding the menu
There are three ways to hide our menu.
Hiding the menu when another row is swiped:
This case is already handled in showMenu() method in our Adapter. Before showing the menu for any row, we first call setShowMenu(false) for all the rows to hide the menu. 2.  Hiding the menu when the back button is pressed (in our Activity):
@Override public void onBackPressed() { if (adapter.isMenuShown()) { adapter.closeMenu(); } else { super.onBackPressed(); } }
3.  Hiding the menu when a user scrolls the list:
recyclerView.setOnScrollChangeListener(new View.OnScrollChangeListener() { @Override public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { adapter.closeMenu(); } });
Though pocket only has a long-press action to show the menu, in this example we've added swipe to show the menu for added functionality. You can hide your menu item on swipe right/left again, but I think it might confuse the user.
Wrapping up
If your app has a very large dataset to show in a RecyclerView, this type of UX might not be the way to go. In that case you should have a bulk-edit sort of functionality. Also if your edit options are more than what you can adjust in a RecyclerView row but you still want to show some quick actions, you can show a Bottomsheet dialog on long press of your item and it can have all your edit options. The Google Drive android app does exactly the same thing.  
0 notes
jeeteshsurana · 6 years ago
Link
pagination and scroll listener in android studio kotlin 
_______________________________________________ implementation _______________________________________________ /*Variables*/ private var pastVisibleItems: Int = 0 private var apiCall: Boolean = true private val layoutManager: LinearLayoutManager? =LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false) private var mPage: Int = 1 /*obersever*/ mHomeViewModel.mHomePropertyList.observe(this, Observer {     if (it != null && !it.data.isNullOrEmpty()) {         apiCall=true         changeUI(true)         mList.addAll(it.data)         mAdapterHome?.notifyDataSetChanged()     } else {         apiCall=false         if (mList.isNullOrEmpty()) {             changeUI(false)         }     } }) /*your recycerlview*/ rvPropertyDetail.addOnScrollListener(object :     RecyclerView.OnScrollListener() {     override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {         pastVisibleItems = layoutManager.findLastCompletelyVisibleItemPosition()         Log.e("Tag","initRecyclerView()-->$pastVisibleItems size()-->${mList.size}")         if (pastVisibleItems >= mList.size-1) {             if (apiCall) {                 loadData()             }         }     } }) /*scroll bottom to call api*/ private fun loadData() {     mPage += 1     mHomeViewModel.getPropertyList(mPage) } _______________________________________________
0 notes
night-finance-site-blog · 8 years ago
Text
@Override protected void onActivityResult(int requstCode, int resultCode, Intent intent) { if (requestCode == REQUEST_EDIT && Bundle extras = intent.getExtraExtras(); if (extras != null) { String result = inten.getString("result"); int pos = extras.getInt("pos"); String title = extras.getInt("title"); boolean checked = extras.getBoolean("checked"); //追加 if (result.equals("add")) { ToDoItem item = new ToDoItem(); item.title = title; item.checked = checked; items.add(item); } //追加 else if (result.equals("edit")) { ToDoItem item = items.get(pos); item.title = item.get(pos); item.checked = checked; } //削除 else if (result.equals("delete")) { items.remove(pos); } //リストビューの更新 ((BaseAdapterlistView.getAdapter()).notifyDataSetChanged(); } } }
EditActivity.java @Overridepublic boolean onOptionItemSelected(MenuItem item) { int itemId = item.getItemId(); if (itemId == MENU_ITEM0 || itemId == MENU_ITEM1) { String result = null; if(itemId == MENU_ITEM0) result = "delete"; if(itemId == MENU_ITEM1) result = pos<0?"add":"edit"; //パラメータの返信 Intent intent = new Intent(); intent.putExtra("result", result); intent.putExtra("pos", pos); intent.putExtra("title", toDoItem.title); intent.putExtra("checked", toDoItem.checked); setResult(Activity.RESULT_OK, intent); finish(); } return true; }
0 notes
clariandroid · 8 years ago
Text
Listas Spinner dinámicas
OPCIÓN 1: Actualizar el array y añadir un nuevo adaptador
1. Crear un ArrayList de datos y añadirlos nuevos.
ArrayList<String> datos_series = new ArrayList<String>(); 
datos_series.add(nombre);
2. Cuando tengamos el ArrayList, creamos un nuevo adaptador y lo añadimos a la lista.
ArrayAdapter<String> adaptador2 = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, datos_series);
adaptador2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
lista.setAdapter(adaptador2);
OPCIÓN 2: Actualizar el adaptador directamente.
1. Creamos la lista, el adaptador y el array.
ArrayList<String> datos = new ArrayList<String>();
ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, datos);
adaptador.setDropDownViewResource (android.R.layout.simple_spinner_dropdown_item);           lista.setAdapter(adaptador);
2. Añadimos los elementos al adaptador.
adaptador.add (nombre);
adaptador2.notifyDataSetChanged(); (no hace falta)
0 notes
iblank-blog · 14 years ago
Text
notifyDataSetChanged不能在非UI主线程调用,在一些比较麻烦的情况下,可以用Handler来解决这个问题
31 notes · View notes
altik-0 · 12 years ago
Text
Android Dev Protips! -- Why isn't NotifyDataSetChanged working?
Fun bug from this afternoon: let's say you have a custom ListAdapter you're working with to fill in data into a ListView, and you're trying to implement a method which allows you to insert a new element into that list. You're competent with the use of Adapters, so you're confident it works - in fact, the model for your add function matches most of the recommendations on StackOverflow:
So, you're confident everything is looking good, yet whenever you actually go to add the new string, the list doesn't update! It comes up when you leave and return to the activity (because you're properly serializing elsewhere in code), but it won't update on the spot.
So you go hunting further into StackOverflow to see if there was something subtle you missed about how to hook up a ListAdapter properly in your ListFragment. Maybe using setListAdapter doesn't properly set up your fragment's ListView as an observer for the adapter? That wouldn't make much sense, but you aren't sure. Perhaps it was something else...
Regardless, you spend a few hours hunting, and nothing comes up. All the errors with NotifyDataSetChanged are pretty dumb errors regarding simply misusing the class, which you've confirmed many times over by now that you haven't done.
So what's the problem?
Well, in case you had the same issues I did this afternoon, it may be that you accidentally let Eclipse fill in your functions for you, so among them you overwrote registerDataSetObserver and unregisterDataSetObserver, and they're filled in with TODO messages rather than calling the superclass's versions. WHOOPS.
The fix: delete those functions, dummy - you're not doing anything in there anyway!
0 notes
shareandopen · 13 years ago
Text
更新ViewPager裡面某一個View的內容
在stackoverflow有一篇文章的問題是"ViewPager PagerAdapter not updating the View",在觀看這篇文章時,剛好我的app應用也有類似的問題,就是該如果更新ViewPager裡某一個View的內容,而不是全部砍掉重建。後來在欣賞外國佬的回答後,有位大大rui.araujo提出一個十分容易解決的方式,就是改寫getItemPosition()
Override getItemPosition in your PagerAdapter like this:
public int getItemPosition(Object object) {     return POSITION_NONE; }
This way, when you call notifyDataSetChanged(), the view pager will remove all views and reload them all. As so the reload effect is obtained.
讓每次呼叫PagerAdapter時,都會被誤判會POSITION_NONE並重新建置所有View。如此一來會造成效能上很大的問題,而且邏輯上也是不太正確。我一開始也是使用這方法來解決我碰到的問題,但後來另一位大大alvarolb為此種錯誤的解法方式做了一些解釋,當中提到為何改寫getItemPosition為永遠回POSITION_NONE是錯誤的邏輯,原文如下:
The notifyDataSetChanged() method on the PagerAdapter will only notify the ViewPager that the underlying pages have changed. For example, if you have create/deleted dynamically pages (adding or removing items from your list) the ViewPager should take care about that. In this case i think that the ViewPager determines if a new view should be deleted or instantiated using the getItemPosition() and getCount() methods.
就連官方SDK文件也說明了ViewPager Adapter notifyDataSetChanged的用意為
PagerAdapter supports data set changes. Data set changes must occur on the main thread and must end with a call to notifyDataSetChanged() similar to AdapterView adapters derived from BaseAdapter. A data set change may involve pages being added, removed, or changing position. The ViewPager will keep the current page active provided the adapter implements the method getItemPosition(Object).
原文看完後,大概是說明Adapter會自動控管View Pager每一頁(Item)的狀態,而notifyDataSetChanged()是用在當View Pager要新增一頁、刪除一頁或改變各個頁面的排列的時候。所以ViewPager Adapter的notifyDataSetChanged自然就不適用於只要更新View Pager裡面某個View的內容的需求啦。所以alvarolb也針對此向需求做了一翻解釋
My approach is to use the setTag() method for any instantiated view in the instantiateItem() method. So when you want to change the data or invalidate the view that you need, you can call the findViewWithTag() method on the viewPager to retrieve the previously instantiated view and modify/use it as you want without having to delete create any new view each time you want to update some value.
關鍵點就是在instantiateItem時,將有需要在後續進行內容更新的view來setTag(),並且在需要更新的時候,使用viewpager的findViewWithTag(),來找到要更新的View並進行更新。講了這麼長的文章,還是來用程式碼來說明會來的直覺一點,我有省略很多細節,主要把精隨分享給大家。
@Override public Object instantiateItem(ViewGroup container, int position) { View view = null; view = mInflater.inflate(R.layout.record_list_layout, null); TextView tvRecord = (TextView) view.findViewById(R.id.tv_record); String key = "tvRecord" + position; // 關鍵點,針對要更新的View來設定Tag,主要是在後續使用ViewPager.findViewWithTag()時,可以找到要更新的View tvRecord.setTag(key); container.addView(view); return view; } // 在後續的應用當中,如果要開始更新View Pager當中某個View的內容時,需要進行下列動作 TextView tvRecord = myViewPager.findViewWithTag("tvRecord1"); // 假設要更新第2頁的TextView // 進行內容更新 if (tvRecord != null ) { tvRecord.setText("update"); } /* end of if */
以上是小弟我了解後的心得,分享給大家,若有錯誤,也煩請指正,謝謝大家啦,下台一鞠躬
0 notes
jeeteshsurana · 6 years ago
Link
The custom Calendar in android studio kotlin
_______________________________________________ Xml _______________________________________________ <?xml version="1.0" encoding="utf-8"?> <LinearLayout     xmlns:android="https://ift.tt/nIICcg"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:background="@drawable/bg_bottom_sheet_dialog_fragment"     android:orientation="vertical">     <androidx.appcompat.widget.LinearLayoutCompat         android:id="@+id/ll_Main"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:layout_marginTop="@dimen/dp_24"         android:orientation="vertical">         <com.android.showMotionRealtor.feature.dasboard.view.schedule.customcalender.CustomCalendar             android:id="@+id/custom_calender"             android:layout_width="match_parent"             android:layout_height="wrap_content" />     </androidx.appcompat.widget.LinearLayoutCompat> </LinearLayout> _______________________________________________ CustomCalendar.kt _______________________________________________ package com.android.showMotionRealtor.feature.dasboard.view.schedule.customcalender import android.app.Dialog import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import com.android.showMotionRealtor.R import com.android.showMotionRealtor.core.util.MAX_CALENDAR_COLUMN import com.android.showMotionRealtor.core.util.mEventDateFormat import com.android.showMotionRealtor.model.CalendarData import com.android.showMotionRealtor.model.EventMessage import com.zendesk.util.DateUtils import java.text.ParseException import java.text.SimpleDateFormat import java.util.* import kotlin.collections.ArrayList /**  * Created by Jeetesh Surana.  */ class CustomCalendar : LinearLayout {     //    private var mUserSelectedDate: Long? = 0L     private var mDialog : Dialog? = null     private var mUserSelectedDate: Date? = null     private var previousButton: ImageView? = null     private var nextButton: ImageView? = null     private var currentDate: TextView? = null     private var rvCalender: RecyclerView? = null     private val formatter = SimpleDateFormat("MMMM yyyy", Locale.ENGLISH)     private val cal = Calendar.getInstance(Locale.ENGLISH)     private val calendarData = ArrayList<CalendarData>()     private val events: ArrayList<EventMessage> = ArrayList()     private var mDateAdapter: DateAdapter? = null     private val mWeekName = ArrayList<String>()     var mCustomCalenderListener: CustomCalenderListener? = null     constructor(context: Context) : super(context)     constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {         setWeekName()         initializeUILayout()         setRecyclerView()         setUpCalenderData()         setPreviousButtonClickEvent()         setNextButtonClickEvent()     }     constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)     private fun initializeUILayout() {         val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater         val mView = inflater.inflate(R.layout.calendar_layout, this)         previousButton = mView.findViewById(R.id.previous_month)         nextButton = mView.findViewById(R.id.next_month)         currentDate = mView.findViewById(R.id.display_current_date)         rvCalender = mView.findViewById(R.id.rv_CustomCalender)     }     private fun setPreviousButtonClickEvent() {         previousButton!!.setOnClickListener {             cal.add(Calendar.MONTH, -1)             setUpCalenderData()         }     }     private fun setNextButtonClickEvent() {         nextButton!!.setOnClickListener {             cal.add(Calendar.MONTH, 1)             setUpCalenderData()         }     }     private fun setUpCalenderData() {         calendarData.clear()         val dayValueInCells = ArrayList<Date>()         val mCal = cal.clone() as Calendar         // set month in cal         mCal.set(Calendar.DAY_OF_MONTH, 1)         // get the start date in week         val firstDayOfTheMonth = mCal.get(Calendar.DAY_OF_WEEK) - 1         mCal.add(Calendar.DAY_OF_MONTH, -firstDayOfTheMonth)         //getting dates         while (dayValueInCells.size < MAX_CALENDAR_COLUMN) {             dayValueInCells.add(mCal.time)             mCal.add(Calendar.DAY_OF_MONTH, 1)         }         //set the title of month         val sDate = formatter.format(cal.time)         currentDate!!.text = sDate         //set the week name         for (i in mWeekName.indices) {             calendarData.add(CalendarData(null, mWeekName[i], 0, false))         }         //set the Dates         for (i in dayValueInCells.indices) {             if (mUserSelectedDate != null && DateUtils.isSameDay(dayValueInCells[i], mUserSelectedDate)) {                 calendarData.add(CalendarData(dayValueInCells[i], null, 1, true))                 mDateAdapter!!.currentSelectedDatePosition(position = i)             } else {                 calendarData.add(CalendarData(dayValueInCells[i], null, 1, false))             }         }         //notify adapter         mDateAdapter!!.notifyDataSetChanged()     }     private fun setWeekName() {         mWeekName.clear()         mWeekName.add("S")         mWeekName.add("M")         mWeekName.add("T")         mWeekName.add("W")         mWeekName.add("T")         mWeekName.add("F")         mWeekName.add("S")     }     private fun setRecyclerView() {         val dateToday = Date()         val reminderDate = convertStringToDate("31-08-2019")         val reminderDate2 = convertStringToDate("25-08-2019")         if (reminderDate!!.after(dateToday) || reminderDate == dateToday) {             events.add(EventMessage(1, "Birthday", reminderDate))         }         if (reminderDate2!!.after(dateToday) || reminderDate == dateToday) {             events.add(EventMessage(2, "Friendship Day !", reminderDate2))         }         val layoutManager = GridLayoutManager(context, 7, RecyclerView.VERTICAL, false)         rvCalender!!.layoutManager = layoutManager         mDateAdapter = DateAdapter(context, calendarData, cal, events, object : DateAdapter.ItemClickListener {             override fun itemClick(position: Int) {                 if (mDialog != null){                     mDialog!!.dismiss()                     mUserSelectedDate = calendarData[position].monthlyDates!!                 }             }         })         rvCalender!!.adapter = mDateAdapter     }     private fun convertStringToDate(dateInString: String): Date? {         val format = SimpleDateFormat(mEventDateFormat, Locale.ENGLISH)         var date: Date? = null         try {             date = format.parse(dateInString)         } catch (e: ParseException) {             e.printStackTrace()         }         return date     }     /*fun setCurrentDate(userSelectedDate: Date) {             mUserSelectedDate = userSelectedDate             setUpCalenderData()         }*/     fun setCalendar(mCal: Calendar) {         mUserSelectedDate = mCal.time         cal.time = mCal.time         setUpCalenderData()     }     fun getCurrentSelectedDate(): Date {         return calendarData[mDateAdapter!!.mLastSelectedDatePosition].monthlyDates!!     }     fun setCustomCalenderListener(customCalenderListener: CustomCalenderListener) {         mCustomCalenderListener = customCalenderListener     }     fun dismissDialog(dialog: Dialog) {         mDialog = dialog     }     interface CustomCalenderListener {         fun currentSelectedDatePosition(position: Int)     } } _______________________________________________ DateAdapter.kt _______________________________________________ package com.android.showMotionRealtor.feature.dasboard.view.schedule.customcalender import android.annotation.SuppressLint import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.appcompat.widget.AppCompatImageView import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.android.showMotionRealtor.R import com.android.showMotionRealtor.model.CalendarData import com.android.showMotionRealtor.model.EventMessage import java.util.* import kotlin.collections.ArrayList /** * Created by Jeetesh Surana. */ class DateAdapter(var context: Context, var mArrayList: java.util.ArrayList<CalendarData> = ArrayList(), var currentDate: Calendar, val allEvents: ArrayList<EventMessage> = ArrayList(), var mItemClickListener: ItemClickListener) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {     var oldPosition: Int = 0     var mLastSelectedDatePosition = -1     private var dateCal = Calendar.getInstance()     private var allDate: Int? = null     private var displayMonth: Int? = null     private var displayYear: Int? = null     private var currentMonth: Int? = null     private var currentYear: Int? = null     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {         var view: View? = null         when (viewType) {             0 -> {                 view = LayoutInflater.from(parent.context).inflate(R.layout.list_days, parent, false)                 return DaysViewHolder(view!!)             }             1 -> {                 view = LayoutInflater.from(parent.context).inflate(R.layout.list_date, parent, false)                 return DateViewHolder(view!!)             }         }         return null!!     }     override fun getItemCount(): Int {         return mArrayList.size     }     override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {         when (holder.itemViewType) {             0 -> {                 (holder as DaysViewHolder).bind(mArrayList[position].mDays!!)             }             1 -> {                 dateCal.time = mArrayList[position].monthlyDates!!                 allDate = dateCal.get(Calendar.DAY_OF_MONTH)                 displayMonth = dateCal.get(Calendar.MONTH) + 1                 displayYear = dateCal.get(Calendar.YEAR)                 currentMonth = currentDate.get(Calendar.MONTH) + 1                 currentYear = currentDate.get(Calendar.YEAR)                 (holder as DateViewHolder).bind(allDate!!, displayMonth!!, displayYear!!, currentMonth!!, currentYear!!)                 setSelectionUI((holder).txtDate, position)                 holder.txtDate.setOnClickListener {                     mItemClickListener.itemClick(position)                     if (mLastSelectedDatePosition != -1 && mLastSelectedDatePosition != position) {                         mArrayList[mLastSelectedDatePosition].isDateSelected = false                     }                     mLastSelectedDatePosition = position                     mArrayList[position].isDateSelected = true                     notifyDataSetChanged()                 }                 val eventCalendar = Calendar.getInstance()                 for (i in 0 until allEvents.size) {                     eventCalendar.time = allEvents[i].reminderDate!!                     if (allDate == eventCalendar.get(Calendar.DAY_OF_MONTH) && displayMonth == eventCalendar.get(Calendar.MONTH) + 1 && displayYear == eventCalendar.get(Calendar.YEAR)) {                         holder.imgEventIcon.visibility = View.VISIBLE                     }                 }             }         }     }     //set the selected position     private fun setSelectionUI(img: TextView, position: Int) {         if (mArrayList[position].isDateSelected) {             img.background = context.resources.getDrawable(R.drawable.circle_background)             img.setTextColor(ContextCompat.getColor(context, R.color.white))         } else {             img.background = null             img.setTextColor(ContextCompat.getColor(context, R.color.grayBlack))         }     }     //set the selected position on item Click     private fun userSelection(img: TextView, position: Int) {         mItemClickListener.itemClick(position)         if (position != oldPosition) {             mArrayList[position].isDateSelected = true             img.setTextColor(ContextCompat.getColor(context, R.color.white))             img.background = context.resources.getDrawable(R.drawable.circle_background)             mArrayList[oldPosition].isDateSelected = false             notifyItemChanged(oldPosition)             oldPosition = position         }     }     inner class DaysViewHolder(view: View) : RecyclerView.ViewHolder(view) {         private var txtDays: TextView = view.findViewById(R.id.txt_Days)         fun bind(days: String) {             txtDays.text = days         }     }     inner class DateViewHolder(view: View) : RecyclerView.ViewHolder(view) {         var txtDate: TextView = view.findViewById(R.id.txt_Date)         var imgEventIcon: AppCompatImageView = view.findViewById(R.id.imgEventIcon)         @SuppressLint("LogNotTimber")         fun bind(dayValue: Int, displayMonth: Int, displayYear: Int, currentMonth: Int, currentYear: Int) {             if (displayMonth == currentMonth && displayYear == currentYear) {                 txtDate.visibility = View.VISIBLE             } else {                 txtDate.visibility = View.GONE             }             txtDate.text = dayValue.toString()         }     }     override fun getItemViewType(position: Int): Int {         return mArrayList[position].viewType     }     interface ItemClickListener {         fun itemClick(position: Int)     }     fun currentSelectedDatePosition(position: Int) {         mLastSelectedDatePosition = position + 7     } } _______________________________________________ implementation _______________________________________________ //set Calendar Date val cal = Calendar.getInstance(Locale.ENGLISH) cal.time = getDateObject(currentDate!!)!! customCalender?.setCalendar(cal) //get Calendar Date override fun onDestroy() {     if (customCalender?.getCurrentSelectedDate() != null) {         EventBus.getDefault().post(CurrentSelectedDate(customCalender?.getCurrentSelectedDate()!!))     }     super.onDestroy() } _______________________________________________
0 notes
jeeteshsurana · 6 years ago
Text
pagination and scroll listener in android studio kotlin
https://ift.tt/2MAnYBx
pagination and scroll listener in android studio kotlin 
_______________________________________________ implementation _______________________________________________ /*Variables*/ private var pastVisibleItems: Int = 0 private var apiCall: Boolean = true private val layoutManager: LinearLayoutManager? =LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false) private var mPage: Int = 1 /*obersever*/ mHomeViewModel.mHomePropertyList.observe(this, Observer {     if (it != null && !it.data.isNullOrEmpty()) {         apiCall=true         changeUI(true)         mList.addAll(it.data)         mAdapterHome?.notifyDataSetChanged()     } else {         apiCall=false         if (mList.isNullOrEmpty()) {             changeUI(false)         }     } }) /*your recycerlview*/ rvPropertyDetail.addOnScrollListener(object :     RecyclerView.OnScrollListener() {     override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {         pastVisibleItems = layoutManager.findLastCompletelyVisibleItemPosition()         Log.e("Tag","initRecyclerView()-->$pastVisibleItems size()-->${mList.size}")         if (pastVisibleItems >= mList.size-1) {             if (apiCall) {                 loadData()             }         }     } }) /*scroll bottom to call api*/ private fun loadData() {     mPage += 1     mHomeViewModel.getPropertyList(mPage) } _______________________________________________
via Blogger https://ift.tt/2JeRDhv
0 notes
jeeteshsurana · 6 years ago
Text
Custom Calendar in android studio kotlin
https://ift.tt/2p3EFMH
The custom Calendar in android studio kotlin
_______________________________________________ Xml _______________________________________________ <?xml version="1.0" encoding="utf-8"?> <LinearLayout     xmlns:android="https://ift.tt/nIICcg"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:background="@drawable/bg_bottom_sheet_dialog_fragment"     android:orientation="vertical">     <androidx.appcompat.widget.LinearLayoutCompat         android:id="@+id/ll_Main"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:layout_marginTop="@dimen/dp_24"         android:orientation="vertical">         <com.android.showMotionRealtor.feature.dasboard.view.schedule.customcalender.CustomCalendar             android:id="@+id/custom_calender"             android:layout_width="match_parent"             android:layout_height="wrap_content" />     </androidx.appcompat.widget.LinearLayoutCompat> </LinearLayout> _______________________________________________ CustomCalendar.kt _______________________________________________ package com.android.showMotionRealtor.feature.dasboard.view.schedule.customcalender import android.app.Dialog import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import com.android.showMotionRealtor.R import com.android.showMotionRealtor.core.util.MAX_CALENDAR_COLUMN import com.android.showMotionRealtor.core.util.mEventDateFormat import com.android.showMotionRealtor.model.CalendarData import com.android.showMotionRealtor.model.EventMessage import com.zendesk.util.DateUtils import java.text.ParseException import java.text.SimpleDateFormat import java.util.* import kotlin.collections.ArrayList /**  * Created by Jeetesh Surana.  */ class CustomCalendar : LinearLayout {     //    private var mUserSelectedDate: Long? = 0L     private var mDialog : Dialog? = null     private var mUserSelectedDate: Date? = null     private var previousButton: ImageView? = null     private var nextButton: ImageView? = null     private var currentDate: TextView? = null     private var rvCalender: RecyclerView? = null     private val formatter = SimpleDateFormat("MMMM yyyy", Locale.ENGLISH)     private val cal = Calendar.getInstance(Locale.ENGLISH)     private val calendarData = ArrayList<CalendarData>()     private val events: ArrayList<EventMessage> = ArrayList()     private var mDateAdapter: DateAdapter? = null     private val mWeekName = ArrayList<String>()     var mCustomCalenderListener: CustomCalenderListener? = null     constructor(context: Context) : super(context)     constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {         setWeekName()         initializeUILayout()         setRecyclerView()         setUpCalenderData()         setPreviousButtonClickEvent()         setNextButtonClickEvent()     }     constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)     private fun initializeUILayout() {         val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater         val mView = inflater.inflate(R.layout.calendar_layout, this)         previousButton = mView.findViewById(R.id.previous_month)         nextButton = mView.findViewById(R.id.next_month)         currentDate = mView.findViewById(R.id.display_current_date)         rvCalender = mView.findViewById(R.id.rv_CustomCalender)     }     private fun setPreviousButtonClickEvent() {         previousButton!!.setOnClickListener {             cal.add(Calendar.MONTH, -1)             setUpCalenderData()         }     }     private fun setNextButtonClickEvent() {         nextButton!!.setOnClickListener {             cal.add(Calendar.MONTH, 1)             setUpCalenderData()         }     }     private fun setUpCalenderData() {         calendarData.clear()         val dayValueInCells = ArrayList<Date>()         val mCal = cal.clone() as Calendar         // set month in cal         mCal.set(Calendar.DAY_OF_MONTH, 1)         // get the start date in week         val firstDayOfTheMonth = mCal.get(Calendar.DAY_OF_WEEK) - 1         mCal.add(Calendar.DAY_OF_MONTH, -firstDayOfTheMonth)         //getting dates         while (dayValueInCells.size < MAX_CALENDAR_COLUMN) {             dayValueInCells.add(mCal.time)             mCal.add(Calendar.DAY_OF_MONTH, 1)         }         //set the title of month         val sDate = formatter.format(cal.time)         currentDate!!.text = sDate         //set the week name         for (i in mWeekName.indices) {             calendarData.add(CalendarData(null, mWeekName[i], 0, false))         }         //set the Dates         for (i in dayValueInCells.indices) {             if (mUserSelectedDate != null && DateUtils.isSameDay(dayValueInCells[i], mUserSelectedDate)) {                 calendarData.add(CalendarData(dayValueInCells[i], null, 1, true))                 mDateAdapter!!.currentSelectedDatePosition(position = i)             } else {                 calendarData.add(CalendarData(dayValueInCells[i], null, 1, false))             }         }         //notify adapter         mDateAdapter!!.notifyDataSetChanged()     }     private fun setWeekName() {         mWeekName.clear()         mWeekName.add("S")         mWeekName.add("M")         mWeekName.add("T")         mWeekName.add("W")         mWeekName.add("T")         mWeekName.add("F")         mWeekName.add("S")     }     private fun setRecyclerView() {         val dateToday = Date()         val reminderDate = convertStringToDate("31-08-2019")         val reminderDate2 = convertStringToDate("25-08-2019")         if (reminderDate!!.after(dateToday) || reminderDate == dateToday) {             events.add(EventMessage(1, "Birthday", reminderDate))         }         if (reminderDate2!!.after(dateToday) || reminderDate == dateToday) {             events.add(EventMessage(2, "Friendship Day !", reminderDate2))         }         val layoutManager = GridLayoutManager(context, 7, RecyclerView.VERTICAL, false)         rvCalender!!.layoutManager = layoutManager         mDateAdapter = DateAdapter(context, calendarData, cal, events, object : DateAdapter.ItemClickListener {             override fun itemClick(position: Int) {                 if (mDialog != null){                     mDialog!!.dismiss()                     mUserSelectedDate = calendarData[position].monthlyDates!!                 }             }         })         rvCalender!!.adapter = mDateAdapter     }     private fun convertStringToDate(dateInString: String): Date? {         val format = SimpleDateFormat(mEventDateFormat, Locale.ENGLISH)         var date: Date? = null         try {             date = format.parse(dateInString)         } catch (e: ParseException) {             e.printStackTrace()         }         return date     }     /*fun setCurrentDate(userSelectedDate: Date) {             mUserSelectedDate = userSelectedDate             setUpCalenderData()         }*/     fun setCalendar(mCal: Calendar) {         mUserSelectedDate = mCal.time         cal.time = mCal.time         setUpCalenderData()     }     fun getCurrentSelectedDate(): Date {         return calendarData[mDateAdapter!!.mLastSelectedDatePosition].monthlyDates!!     }     fun setCustomCalenderListener(customCalenderListener: CustomCalenderListener) {         mCustomCalenderListener = customCalenderListener     }     fun dismissDialog(dialog: Dialog) {         mDialog = dialog     }     interface CustomCalenderListener {         fun currentSelectedDatePosition(position: Int)     } } _______________________________________________ DateAdapter.kt _______________________________________________ package com.android.showMotionRealtor.feature.dasboard.view.schedule.customcalender import android.annotation.SuppressLint import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.appcompat.widget.AppCompatImageView import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.android.showMotionRealtor.R import com.android.showMotionRealtor.model.CalendarData import com.android.showMotionRealtor.model.EventMessage import java.util.* import kotlin.collections.ArrayList /** * Created by Jeetesh Surana. */ class DateAdapter(var context: Context, var mArrayList: java.util.ArrayList<CalendarData> = ArrayList(), var currentDate: Calendar, val allEvents: ArrayList<EventMessage> = ArrayList(), var mItemClickListener: ItemClickListener) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {     var oldPosition: Int = 0     var mLastSelectedDatePosition = -1     private var dateCal = Calendar.getInstance()     private var allDate: Int? = null     private var displayMonth: Int? = null     private var displayYear: Int? = null     private var currentMonth: Int? = null     private var currentYear: Int? = null     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {         var view: View? = null         when (viewType) {             0 -> {                 view = LayoutInflater.from(parent.context).inflate(R.layout.list_days, parent, false)                 return DaysViewHolder(view!!)             }             1 -> {                 view = LayoutInflater.from(parent.context).inflate(R.layout.list_date, parent, false)                 return DateViewHolder(view!!)             }         }         return null!!     }     override fun getItemCount(): Int {         return mArrayList.size     }     override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {         when (holder.itemViewType) {             0 -> {                 (holder as DaysViewHolder).bind(mArrayList[position].mDays!!)             }             1 -> {                 dateCal.time = mArrayList[position].monthlyDates!!                 allDate = dateCal.get(Calendar.DAY_OF_MONTH)                 displayMonth = dateCal.get(Calendar.MONTH) + 1                 displayYear = dateCal.get(Calendar.YEAR)                 currentMonth = currentDate.get(Calendar.MONTH) + 1                 currentYear = currentDate.get(Calendar.YEAR)                 (holder as DateViewHolder).bind(allDate!!, displayMonth!!, displayYear!!, currentMonth!!, currentYear!!)                 setSelectionUI((holder).txtDate, position)             ��   holder.txtDate.setOnClickListener {                     mItemClickListener.itemClick(position)                     if (mLastSelectedDatePosition != -1 && mLastSelectedDatePosition != position) {                         mArrayList[mLastSelectedDatePosition].isDateSelected = false                     }                     mLastSelectedDatePosition = position                     mArrayList[position].isDateSelected = true                     notifyDataSetChanged()                 }                 val eventCalendar = Calendar.getInstance()                 for (i in 0 until allEvents.size) {                     eventCalendar.time = allEvents[i].reminderDate!!                     if (allDate == eventCalendar.get(Calendar.DAY_OF_MONTH) && displayMonth == eventCalendar.get(Calendar.MONTH) + 1 && displayYear == eventCalendar.get(Calendar.YEAR)) {                         holder.imgEventIcon.visibility = View.VISIBLE                     }                 }             }         }     }     //set the selected position     private fun setSelectionUI(img: TextView, position: Int) {         if (mArrayList[position].isDateSelected) {             img.background = context.resources.getDrawable(R.drawable.circle_background)             img.setTextColor(ContextCompat.getColor(context, R.color.white))         } else {             img.background = null             img.setTextColor(ContextCompat.getColor(context, R.color.grayBlack))         }     }     //set the selected position on item Click     private fun userSelection(img: TextView, position: Int) {         mItemClickListener.itemClick(position)         if (position != oldPosition) {             mArrayList[position].isDateSelected = true             img.setTextColor(ContextCompat.getColor(context, R.color.white))             img.background = context.resources.getDrawable(R.drawable.circle_background)             mArrayList[oldPosition].isDateSelected = false             notifyItemChanged(oldPosition)             oldPosition = position         }     }     inner class DaysViewHolder(view: View) : RecyclerView.ViewHolder(view) {         private var txtDays: TextView = view.findViewById(R.id.txt_Days)         fun bind(days: String) {             txtDays.text = days         }     }     inner class DateViewHolder(view: View) : RecyclerView.ViewHolder(view) {         var txtDate: TextView = view.findViewById(R.id.txt_Date)         var imgEventIcon: AppCompatImageView = view.findViewById(R.id.imgEventIcon)         @SuppressLint("LogNotTimber")         fun bind(dayValue: Int, displayMonth: Int, displayYear: Int, currentMonth: Int, currentYear: Int) {             if (displayMonth == currentMonth && displayYear == currentYear) {                 txtDate.visibility = View.VISIBLE             } else {                 txtDate.visibility = View.GONE             }             txtDate.text = dayValue.toString()         }     }     override fun getItemViewType(position: Int): Int {         return mArrayList[position].viewType     }     interface ItemClickListener {         fun itemClick(position: Int)     }     fun currentSelectedDatePosition(position: Int) {         mLastSelectedDatePosition = position + 7     } } _______________________________________________ implementation _______________________________________________ //set Calendar Date val cal = Calendar.getInstance(Locale.ENGLISH) cal.time = getDateObject(currentDate!!)!! customCalender?.setCalendar(cal) //get Calendar Date override fun onDestroy() {     if (customCalender?.getCurrentSelectedDate() != null) {         EventBus.getDefault().post(CurrentSelectedDate(customCalender?.getCurrentSelectedDate()!!))     }     super.onDestroy() } _______________________________________________
via Blogger https://ift.tt/2Mzz1Lb
0 notes
jeeteshsurana · 6 years ago
Text
Custom Calendar in android studio kotlin
https://ift.tt/2Ho5Zep
Custom Calendar in android studio kotlin 
_______________________________________________
Xml 
_______________________________________________
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="https://ift.tt/nIICcg"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/bg_bottom_sheet_dialog_fragment"
    android:orientation="vertical">
    <androidx.appcompat.widget.LinearLayoutCompat
        android:id="@+id/ll_Main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_24"
        android:orientation="vertical">
        <com.android.showMotionRealtor.feature.dasboard.view.schedule.customcalender.CustomCalendar
            android:id="@+id/custom_calender"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </androidx.appcompat.widget.LinearLayoutCompat>
</LinearLayout>
_______________________________________________
CustomCalendar.kt
_______________________________________________
package com.android.showMotionRealtor.feature.dasboard.view.schedule.customcalender
import android.app.Dialog
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.showMotionRealtor.R
import com.android.showMotionRealtor.core.util.MAX_CALENDAR_COLUMN
import com.android.showMotionRealtor.core.util.mEventDateFormat
import com.android.showMotionRealtor.model.CalendarData
import com.android.showMotionRealtor.model.EventMessage
import com.zendesk.util.DateUtils
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.ArrayList
/**
 * Created by Jeetesh Surana.
 */
class CustomCalendar : LinearLayout {
    //    private var mUserSelectedDate: Long? = 0L
    private var mDialog : Dialog? = null
    private var mUserSelectedDate: Date? = null
    private var previousButton: ImageView? = null
    private var nextButton: ImageView? = null
    private var currentDate: TextView? = null
    private var rvCalender: RecyclerView? = null
    private val formatter = SimpleDateFormat("MMMM yyyy", Locale.ENGLISH)
    private val cal = Calendar.getInstance(Locale.ENGLISH)
    private val calendarData = ArrayList<CalendarData>()
    private val events: ArrayList<EventMessage> = ArrayList()
    private var mDateAdapter: DateAdapter? = null
    private val mWeekName = ArrayList<String>()
    var mCustomCalenderListener: CustomCalenderListener? = null
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        setWeekName()
        initializeUILayout()
        setRecyclerView()
        setUpCalenderData()
        setPreviousButtonClickEvent()
        setNextButtonClickEvent()
    }
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
    private fun initializeUILayout() {
        val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        val mView = inflater.inflate(R.layout.calendar_layout, this)
        previousButton = mView.findViewById(R.id.previous_month)
        nextButton = mView.findViewById(R.id.next_month)
        currentDate = mView.findViewById(R.id.display_current_date)
        rvCalender = mView.findViewById(R.id.rv_CustomCalender)
    }
    private fun setPreviousButtonClickEvent() {
        previousButton!!.setOnClickListener {
            cal.add(Calendar.MONTH, -1)
            setUpCalenderData()
        }
    }
    private fun setNextButtonClickEvent() {
        nextButton!!.setOnClickListener {
            cal.add(Calendar.MONTH, 1)
            setUpCalenderData()
        }
    }
    private fun setUpCalenderData() {
        calendarData.clear()
        val dayValueInCells = ArrayList<Date>()
        val mCal = cal.clone() as Calendar
        // set month in cal
        mCal.set(Calendar.DAY_OF_MONTH, 1)
        // get the start date in week
        val firstDayOfTheMonth = mCal.get(Calendar.DAY_OF_WEEK) - 1
        mCal.add(Calendar.DAY_OF_MONTH, -firstDayOfTheMonth)
        //getting dates
        while (dayValueInCells.size < MAX_CALENDAR_COLUMN) {
            dayValueInCells.add(mCal.time)
            mCal.add(Calendar.DAY_OF_MONTH, 1)
        }
        //set the title of month
        val sDate = formatter.format(cal.time)
        currentDate!!.text = sDate
        //set the week name
        for (i in mWeekName.indices) {
            calendarData.add(CalendarData(null, mWeekName[i], 0, false))
        }
        //set the Dates
        for (i in dayValueInCells.indices) {
            if (mUserSelectedDate != null && DateUtils.isSameDay(dayValueInCells[i], mUserSelectedDate)) {
                calendarData.add(CalendarData(dayValueInCells[i], null, 1, true))
                mDateAdapter!!.currentSelectedDatePosition(position = i)
            } else {
                calendarData.add(CalendarData(dayValueInCells[i], null, 1, false))
            }
        }
        //notify adapter
        mDateAdapter!!.notifyDataSetChanged()
    }
    private fun setWeekName() {
        mWeekName.clear()
        mWeekName.add("S")
        mWeekName.add("M")
        mWeekName.add("T")
        mWeekName.add("W")
        mWeekName.add("T")
        mWeekName.add("F")
        mWeekName.add("S")
    }
    private fun setRecyclerView() {
        val dateToday = Date()
        val reminderDate = convertStringToDate("31-08-2019")
        val reminderDate2 = convertStringToDate("25-08-2019")
        if (reminderDate!!.after(dateToday) || reminderDate == dateToday) {
            events.add(EventMessage(1, "Birthday", reminderDate))
        }
        if (reminderDate2!!.after(dateToday) || reminderDate == dateToday) {
            events.add(EventMessage(2, "Friendship Day !", reminderDate2))
        }
        val layoutManager = GridLayoutManager(context, 7, RecyclerView.VERTICAL, false)
        rvCalender!!.layoutManager = layoutManager
        mDateAdapter = DateAdapter(context, calendarData, cal, events, object : DateAdapter.ItemClickListener {
            override fun itemClick(position: Int) {
                if (mDialog != null){
                    mDialog!!.dismiss()
                    mUserSelectedDate = calendarData[position].monthlyDates!!
                }
            }
        })
        rvCalender!!.adapter = mDateAdapter
    }
    private fun convertStringToDate(dateInString: String): Date? {
        val format = SimpleDateFormat(mEventDateFormat, Locale.ENGLISH)
        var date: Date? = null
        try {
            date = format.parse(dateInString)
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return date
    }
    /*
        fun setCurrentDate(userSelectedDate: Date) {
            mUserSelectedDate = userSelectedDate
            setUpCalenderData()
        }*/
    fun setCalendar(mCal: Calendar) {
        mUserSelectedDate = mCal.time
        cal.time = mCal.time
        setUpCalenderData()
    }
    fun getCurrentSelectedDate(): Date {
        return calendarData[mDateAdapter!!.mLastSelectedDatePosition].monthlyDates!!
    }
    fun setCustomCalenderListener(customCalenderListener: CustomCalenderListener) {
        mCustomCalenderListener = customCalenderListener
    }
    fun dismissDialog(dialog: Dialog) {
        mDialog = dialog
    }
    interface CustomCalenderListener {
        fun currentSelectedDatePosition(position: Int)
    }
}
_______________________________________________
DateAdapter.kt
_______________________________________________
package com.android.showMotionRealtor.feature.dasboard.view.schedule.customcalender
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.android.showMotionRealtor.R
import com.android.showMotionRealtor.model.CalendarData
import com.android.showMotionRealtor.model.EventMessage
import java.util.*
import kotlin.collections.ArrayList
/**
 * Created by Abhin.
 */
class DateAdapter(var context: Context, var mArrayList: java.util.ArrayList<CalendarData> = ArrayList(), var currentDate: Calendar, val allEvents: ArrayList<EventMessage> = ArrayList(), var mItemClickListener: ItemClickListener) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    var oldPosition: Int = 0
    var mLastSelectedDatePosition = -1
    private var dateCal = Calendar.getInstance()
    private var allDate: Int? = null
    private var displayMonth: Int? = null
    private var displayYear: Int? = null
    private var currentMonth: Int? = null
    private var currentYear: Int? = null
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        var view: View? = null
        when (viewType) {
            0 -> {
                view = LayoutInflater.from(parent.context).inflate(R.layout.list_days, parent, false)
                return DaysViewHolder(view!!)
            }
            1 -> {
                view = LayoutInflater.from(parent.context).inflate(R.layout.list_date, parent, false)
                return DateViewHolder(view!!)
            }
        }
        return null!!
    }
    override fun getItemCount(): Int {
        return mArrayList.size
    }
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder.itemViewType) {
            0 -> {
                (holder as DaysViewHolder).bind(mArrayList[position].mDays!!)
            }
            1 -> {
                dateCal.time = mArrayList[position].monthlyDates!!
                allDate = dateCal.get(Calendar.DAY_OF_MONTH)
                displayMonth = dateCal.get(Calendar.MONTH) + 1
                displayYear = dateCal.get(Calendar.YEAR)
                currentMonth = currentDate.get(Calendar.MONTH) + 1
                currentYear = currentDate.get(Calendar.YEAR)
                (holder as DateViewHolder).bind(allDate!!, displayMonth!!, displayYear!!, currentMonth!!, currentYear!!)
                setSelectionUI((holder).txtDate, position)
                holder.txtDate.setOnClickListener {
                    mItemClickListener.itemClick(position)
                    if (mLastSelectedDatePosition != -1 && mLastSelectedDatePosition != position) {
                        mArrayList[mLastSelectedDatePosition].isDateSelected = false
                    }
                    mLastSelectedDatePosition = position
                    mArrayList[position].isDateSelected = true
                    notifyDataSetChanged()
                }
                val eventCalendar = Calendar.getInstance()
                for (i in 0 until allEvents.size) {
                    eventCalendar.time = allEvents[i].reminderDate!!
                    if (allDate == eventCalendar.get(Calendar.DAY_OF_MONTH) && displayMonth == eventCalendar.get(Calendar.MONTH) + 1 && displayYear == eventCalendar.get(Calendar.YEAR)) {
                        holder.imgEventIcon.visibility = View.VISIBLE
                    }
                }
            }
        }
    }
    //set the selected position
    private fun setSelectionUI(img: TextView, position: Int) {
        if (mArrayList[position].isDateSelected) {
            img.background = context.resources.getDrawable(R.drawable.circle_background)
            img.setTextColor(ContextCompat.getColor(context, R.color.white))
        } else {
            img.background = null
            img.setTextColor(ContextCompat.getColor(context, R.color.grayBlack))
        }
    }
    //set the selected position on item Click
    private fun userSelection(img: TextView, position: Int) {
        mItemClickListener.itemClick(position)
        if (position != oldPosition) {
            mArrayList[position].isDateSelected = true
            img.setTextColor(ContextCompat.getColor(context, R.color.white))
            img.background = context.resources.getDrawable(R.drawable.circle_background)
            mArrayList[oldPosition].isDateSelected = false
            notifyItemChanged(oldPosition)
            oldPosition = position
        }
    }
    inner class DaysViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        private var txtDays: TextView = view.findViewById(R.id.txt_Days)
        fun bind(days: String) {
            txtDays.text = days
        }
    }
    inner class DateViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        var txtDate: TextView = view.findViewById(R.id.txt_Date)
        var imgEventIcon: AppCompatImageView = view.findViewById(R.id.imgEventIcon)
        @SuppressLint("LogNotTimber")
        fun bind(dayValue: Int, displayMonth: Int, displayYear: Int, currentMonth: Int, currentYear: Int) {
            if (displayMonth == currentMonth && displayYear == currentYear) {
                txtDate.visibility = View.VISIBLE
            } else {
                txtDate.visibility = View.GONE
            }
            txtDate.text = dayValue.toString()
        }
    }
    override fun getItemViewType(position: Int): Int {
        return mArrayList[position].viewType
    }
    interface ItemClickListener {
        fun itemClick(position: Int)
    }
    fun currentSelectedDatePosition(position: Int) {
        mLastSelectedDatePosition = position + 7
    }
}
_______________________________________________
implementation
_______________________________________________
//set Calendar Date
val cal = Calendar.getInstance(Locale.ENGLISH)
cal.time = getDateObject(currentDate!!)!!
customCalender?.setCalendar(cal)
//get Calendar Date
override fun onDestroy() {
    if (customCalender?.getCurrentSelectedDate() != null) {
        EventBus.getDefault().post(CurrentSelectedDate(customCalender?.getCurrentSelectedDate()!!))
    }
    super.onDestroy()
}
_______________________________________________
via Blogger https://ift.tt/2L5Lu7r
0 notes
android-arsenal · 8 years ago
Text
LoopingViewPager
A ViewPager and a PagerAdapter that can:
AutoScroll (On/Off able)
Infinite Loop (On/Off able)
ViewPager's height can be wrap_content
Adjustable auto scroll interval
Won't scroll nor loop if there is only 1 item
Works well with notifyDataSetChanged()
Supports page indicators
from The Android Arsenal http://ift.tt/2p05i4z
0 notes